streamline_annotate.c 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417
  1. /**
  2. * Copyright (C) 2014-2023 by Arm Limited. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * 3. Neither the name of the copyright holder nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  22. * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  25. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #ifndef _GNU_SOURCE
  32. #define _GNU_SOURCE
  33. #endif
  34. #include "streamline_annotate.h"
  35. #include "streamline_annotate_logging.h"
  36. #include <arpa/inet.h>
  37. #include <errno.h>
  38. #include <fcntl.h>
  39. #include <pthread.h>
  40. #include <semaphore.h>
  41. #include <stdbool.h>
  42. #include <stddef.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <sys/prctl.h>
  47. #include <sys/socket.h>
  48. #include <sys/syscall.h>
  49. #include <sys/types.h>
  50. #include <sys/un.h>
  51. #include <time.h>
  52. #include <unistd.h>
  53. #define THREAD_BUFFER_SIZE (1 << 16)
  54. #define THREAD_BUFFER_MASK (THREAD_BUFFER_SIZE - 1)
  55. #ifdef TCP_ANNOTATIONS
  56. #define STREAMLINE_ANNOTATE_PARENT 8082
  57. #define STREAMLINE_ANNOTATE 8083
  58. #else
  59. #define STREAMLINE_ANNOTATE_PARENT "\0streamline-annotate-parent"
  60. #define STREAMLINE_ANNOTATE "\0streamline-annotate"
  61. #endif
  62. static const char gator_annotate_handshake[] = "ANNOTATE 5\n";
  63. static const int gator_minimum_version = 24;
  64. static const uint8_t HEADER_UTF8 = 0x01;
  65. static const uint8_t HEADER_UTF8_COLOR = 0x02;
  66. static const uint8_t HEADER_CHANNEL_NAME = 0x03;
  67. static const uint8_t HEADER_GROUP_NAME = 0x04;
  68. static const uint8_t HEADER_VISUAL = 0x05;
  69. static const uint8_t HEADER_MARKER = 0x06;
  70. static const uint8_t HEADER_MARKER_COLOR = 0x07;
  71. static const uint8_t HEADER_COUNTER = 0x08;
  72. static const uint8_t HEADER_COUNTER_VALUE = 0x09;
  73. static const uint8_t HEADER_ACTIVITY_SWITCH = 0x0a;
  74. static const uint8_t HEADER_CAM_TRACK = 0x0b;
  75. static const uint8_t HEADER_CAM_JOB = 0x0c;
  76. static const uint8_t HEADER_CAM_VIEW_NAME = 0x0d;
  77. static const uint8_t HEADER_CAM_JOB_START = 0x0e;
  78. static const uint8_t HEADER_CAM_JOB_SET_DEPS = 0x0f;
  79. static const uint8_t HEADER_CAM_JOB_STOP = 0x10;
  80. static const uint32_t SIZE_COLOR = 4;
  81. static const uint32_t MAXSIZE_PACK_INT = 5;
  82. static const uint32_t MAXSIZE_PACK_LONG = 10;
  83. static const uint64_t NS_PER_S = 1000000000;
  84. struct gator_thread {
  85. struct gator_thread * next;
  86. const char * oob_data;
  87. /* oob_data must be written before oob_length */
  88. size_t oob_length;
  89. /* Posted when data is sent */
  90. sem_t sem;
  91. int fd;
  92. int tid;
  93. uint32_t write_pos;
  94. uint32_t read_pos;
  95. bool exited;
  96. char buf[THREAD_BUFFER_SIZE];
  97. };
  98. struct gator_counter {
  99. struct gator_counter * next;
  100. const char * title;
  101. const char * name;
  102. const char * units;
  103. const char * description;
  104. const char ** activities;
  105. uint32_t * activity_colors;
  106. size_t activity_count;
  107. int per_cpu;
  108. int average_selection;
  109. int average_cores;
  110. int percentage;
  111. enum gator_annotate_counter_class counter_class;
  112. enum gator_annotate_display display;
  113. enum gator_annotate_series_composition series_composition;
  114. enum gator_annotate_rendering_type rendering_type;
  115. uint32_t id;
  116. uint32_t modifier;
  117. uint32_t cores;
  118. uint32_t color;
  119. };
  120. struct gator_cam_track {
  121. struct gator_cam_track * next;
  122. const char * name;
  123. uint32_t view_uid;
  124. uint32_t track_uid;
  125. uint32_t parent_track;
  126. };
  127. struct gator_cam_name {
  128. struct gator_cam_name * next;
  129. const char * name;
  130. uint32_t view_uid;
  131. };
  132. struct gator_state {
  133. struct gator_thread * threads;
  134. struct gator_counter * counters;
  135. struct gator_cam_track * cam_tracks;
  136. struct gator_cam_name * cam_names;
  137. /* Post to request asynchronous send of data */
  138. sem_t sender_sem;
  139. /* Post to request synchronous send of data */
  140. sem_t sync_sem;
  141. /* Posted when synchronous send of data has completed */
  142. sem_t sync_waiter_sem;
  143. pthread_key_t key;
  144. int parent_fd;
  145. bool initialized;
  146. bool capturing;
  147. bool forked;
  148. bool resend_state;
  149. };
  150. static struct gator_state gator_state;
  151. /* Intentionally exported */
  152. uint8_t gator_dont_mangle_keys;
  153. static int gator_socket_cloexec(int domain, int type, int protocol)
  154. {
  155. #ifdef SOCK_CLOEXEC
  156. return socket(domain, type | SOCK_CLOEXEC, protocol);
  157. #else
  158. const int sock = socket(domain, type, protocol);
  159. if (sock < 0)
  160. return -1;
  161. const int fdf = fcntl(sock, F_GETFD);
  162. if ((fdf == -1) || (fcntl(sock, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
  163. close(sock);
  164. return -1;
  165. }
  166. return sock;
  167. #endif
  168. }
  169. static void gator_destructor(void * value)
  170. {
  171. struct gator_thread * const thread = (struct gator_thread *) value;
  172. if (thread != NULL) {
  173. thread->exited = true;
  174. }
  175. }
  176. void gator_annotate_fork_child(void)
  177. {
  178. /* Single threaded at this point */
  179. struct gator_thread * thread;
  180. pthread_setspecific(gator_state.key, NULL);
  181. for (thread = gator_state.threads; thread != NULL; thread = thread->next) {
  182. thread->exited = true;
  183. thread->read_pos = thread->write_pos;
  184. }
  185. gator_state.forked = true;
  186. }
  187. void gator_annotate_flush(void)
  188. {
  189. if (gator_state.capturing) {
  190. /* Request synchronous send of data */
  191. sem_post(&gator_state.sync_sem);
  192. /* Wake up sender */
  193. sem_post(&gator_state.sender_sem);
  194. /* Wait for completion */
  195. sem_wait(&gator_state.sync_waiter_sem);
  196. }
  197. }
  198. static void gator_set_ts(struct timespec * const ts, const uint64_t time)
  199. {
  200. ts->tv_sec = time / NS_PER_S;
  201. ts->tv_nsec = time % NS_PER_S;
  202. }
  203. static uint64_t gator_time(const clockid_t clk_id)
  204. {
  205. struct timespec ts;
  206. if (clock_gettime(clk_id, &ts) != 0) {
  207. return ~0;
  208. }
  209. return NS_PER_S * ts.tv_sec + ts.tv_nsec;
  210. }
  211. uint64_t gator_get_time(void)
  212. {
  213. #ifndef CLOCK_MONOTONIC_RAW
  214. /* Android doesn't have this defined but it was added in Linux 2.6.28 */
  215. #define CLOCK_MONOTONIC_RAW 4
  216. #endif
  217. return gator_time(CLOCK_MONOTONIC_RAW);
  218. }
  219. static int get_correct_socket_fd(bool for_parent)
  220. {
  221. #ifdef TCP_ANNOTATIONS
  222. const int fd = gator_socket_cloexec(AF_INET, SOCK_STREAM, 0);
  223. if (fd < 0)
  224. return -1;
  225. struct sockaddr_in addr;
  226. addr.sin_family = AF_INET;
  227. addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  228. if (for_parent) {
  229. addr.sin_port = htons(STREAMLINE_ANNOTATE_PARENT);
  230. }
  231. else {
  232. addr.sin_port = htons(STREAMLINE_ANNOTATE);
  233. }
  234. if (connect(fd, (const struct sockaddr *) &addr, sizeof(addr)) != 0) {
  235. close(fd);
  236. return -1;
  237. }
  238. #else
  239. const int fd = gator_socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
  240. if (fd < 0) {
  241. return -1;
  242. }
  243. struct sockaddr_un addr = {0};
  244. addr.sun_family = AF_UNIX;
  245. char * socket_name = STREAMLINE_ANNOTATE;
  246. size_t name_len = sizeof(STREAMLINE_ANNOTATE);
  247. if (for_parent) {
  248. socket_name = STREAMLINE_ANNOTATE_PARENT;
  249. name_len = sizeof(STREAMLINE_ANNOTATE_PARENT);
  250. }
  251. memcpy(addr.sun_path, socket_name, name_len);
  252. if (connect(fd, (const struct sockaddr *) &addr, offsetof(struct sockaddr_un, sun_path) + name_len - 1) != 0) {
  253. close(fd);
  254. return -1;
  255. }
  256. #endif
  257. return fd;
  258. }
  259. static bool gator_parent_connect(void)
  260. {
  261. const int fd = get_correct_socket_fd(/* for_parent= */ true);
  262. if (fd < 0) {
  263. return false;
  264. }
  265. gator_state.parent_fd = fd;
  266. return true;
  267. }
  268. static uint32_t gator_buf_pos(const uint32_t pos)
  269. {
  270. return pos & THREAD_BUFFER_MASK;
  271. }
  272. static uint32_t gator_buf_write_byte(char * const buf, uint32_t * const write_pos_ptr, char b)
  273. {
  274. const uint32_t write_pos = *write_pos_ptr;
  275. buf[write_pos] = b;
  276. *write_pos_ptr = gator_buf_pos(write_pos + 1);
  277. return 1;
  278. }
  279. static uint32_t gator_buf_write_uint32(char * const buf, uint32_t * const write_pos_ptr, uint32_t i)
  280. {
  281. const uint32_t write_pos = *write_pos_ptr;
  282. buf[gator_buf_pos(write_pos + 0)] = i & 0xff;
  283. buf[gator_buf_pos(write_pos + 1)] = (i >> 8) & 0xff;
  284. buf[gator_buf_pos(write_pos + 2)] = (i >> 16) & 0xff;
  285. buf[gator_buf_pos(write_pos + 3)] = (i >> 24) & 0xff;
  286. *write_pos_ptr = gator_buf_pos(write_pos + sizeof(uint32_t));
  287. return sizeof(uint32_t);
  288. }
  289. static uint32_t gator_buf_write_color(char * const buf, uint32_t * const write_pos_ptr, const uint32_t color)
  290. {
  291. const uint32_t write_pos = *write_pos_ptr;
  292. buf[gator_buf_pos(write_pos + 0)] = (color >> 8) & 0xff;
  293. buf[gator_buf_pos(write_pos + 1)] = (color >> 16) & 0xff;
  294. buf[gator_buf_pos(write_pos + 2)] = (color >> 24) & 0xff;
  295. buf[gator_buf_pos(write_pos + 3)] = (color >> 0) & 0xff;
  296. *write_pos_ptr = gator_buf_pos(write_pos + 4);
  297. return 4;
  298. }
  299. static uint32_t gator_buf_write_int(char * const buf, uint32_t * const write_pos_ptr, int32_t x)
  300. {
  301. const uint32_t write_pos = *write_pos_ptr;
  302. int packed_bytes = 0;
  303. int more = true;
  304. while (more) {
  305. /* low order 7 bits of x */
  306. char b = x & 0x7f;
  307. x >>= 7;
  308. if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) {
  309. more = false;
  310. }
  311. else {
  312. b |= 0x80;
  313. }
  314. buf[gator_buf_pos(write_pos + packed_bytes)] = b;
  315. packed_bytes++;
  316. }
  317. *write_pos_ptr = gator_buf_pos(write_pos + packed_bytes);
  318. return packed_bytes;
  319. }
  320. static uint32_t gator_buf_write_long(char * const buf, uint32_t * const write_pos_ptr, int64_t x)
  321. {
  322. const uint32_t write_pos = *write_pos_ptr;
  323. int packed_bytes = 0;
  324. int more = true;
  325. while (more) {
  326. /* low order 7 bits of x */
  327. char b = x & 0x7f;
  328. x >>= 7;
  329. if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) {
  330. more = false;
  331. }
  332. else {
  333. b |= 0x80;
  334. }
  335. buf[gator_buf_pos(write_pos + packed_bytes)] = b;
  336. packed_bytes++;
  337. }
  338. *write_pos_ptr = gator_buf_pos(write_pos + packed_bytes);
  339. return packed_bytes;
  340. }
  341. static uint32_t gator_buf_write_time(char * const buf, uint32_t * const write_pos_ptr)
  342. {
  343. return gator_buf_write_long(buf, write_pos_ptr, gator_get_time());
  344. }
  345. static uint32_t gator_buf_write_bytes(char * const buf,
  346. uint32_t * const write_pos_ptr,
  347. const char * const data,
  348. const uint32_t count)
  349. {
  350. if (count > 0) {
  351. const uint32_t write_pos = *write_pos_ptr;
  352. if (write_pos + count <= THREAD_BUFFER_SIZE) {
  353. memcpy(buf + write_pos, data, count);
  354. }
  355. else {
  356. const uint32_t first = THREAD_BUFFER_SIZE - write_pos;
  357. const uint32_t second = count - first;
  358. memcpy(buf + write_pos, data, first);
  359. memcpy(buf, data + first, second);
  360. }
  361. *write_pos_ptr = gator_buf_pos(write_pos + count);
  362. }
  363. return count;
  364. }
  365. static int gator_connect(const int tid)
  366. {
  367. const int fd = get_correct_socket_fd(/* for_parent= */ false);
  368. if (fd < 0) {
  369. return -1;
  370. }
  371. /* Send tid as gatord cannot autodiscover it and the per process unique id */
  372. uint32_t write_pos = 0;
  373. char buf[sizeof(gator_annotate_handshake) + 2 * sizeof(uint32_t) + 1];
  374. gator_buf_write_bytes(buf, &write_pos, gator_annotate_handshake, sizeof(gator_annotate_handshake) - 1);
  375. gator_buf_write_uint32(buf, &write_pos, tid);
  376. gator_buf_write_uint32(buf, &write_pos, getpid());
  377. gator_buf_write_byte(buf, &write_pos, gator_dont_mangle_keys);
  378. const ssize_t bytes = send(fd, buf, write_pos, MSG_NOSIGNAL);
  379. if (bytes != (ssize_t) write_pos) {
  380. close(fd);
  381. return -1;
  382. }
  383. return fd;
  384. }
  385. static void gator_start_capturing(void)
  386. {
  387. if (__sync_bool_compare_and_swap(&gator_state.capturing, false, true)) {
  388. gator_state.resend_state = true;
  389. }
  390. }
  391. static void gator_stop_capturing(void)
  392. {
  393. if (__sync_bool_compare_and_swap(&gator_state.capturing, true, false)) {
  394. struct gator_thread * thread;
  395. for (thread = gator_state.threads; thread != NULL; thread = thread->next) {
  396. thread->read_pos = thread->write_pos;
  397. thread->oob_length = 0;
  398. sem_post(&thread->sem);
  399. if (thread->fd > 0) {
  400. close(thread->fd);
  401. thread->fd = -1;
  402. }
  403. }
  404. }
  405. }
  406. static bool gator_send(struct gator_thread * const thread, const uint32_t write_pos)
  407. {
  408. size_t write;
  409. ssize_t bytes;
  410. if (write_pos > thread->read_pos) {
  411. write = write_pos - thread->read_pos;
  412. bytes = send(thread->fd, thread->buf + thread->read_pos, write, MSG_NOSIGNAL);
  413. if (bytes == 0) {
  414. //not an error reattempt.
  415. return true;
  416. }
  417. if (bytes < 0) {
  418. return false;
  419. }
  420. thread->read_pos = gator_buf_pos(thread->read_pos + bytes);
  421. }
  422. else {
  423. write = THREAD_BUFFER_SIZE - thread->read_pos;
  424. bytes = send(thread->fd, thread->buf + thread->read_pos, write, MSG_NOSIGNAL);
  425. if (bytes == 0) {
  426. //not an error reattempt.
  427. return true;
  428. }
  429. if (bytes < 0) {
  430. return false;
  431. }
  432. thread->read_pos = gator_buf_pos(thread->read_pos + bytes);
  433. if (write == (size_t) bytes) {
  434. /* Don't write more on a short write to be fair to other threads */
  435. write = write_pos;
  436. bytes = send(thread->fd, thread->buf, write, MSG_NOSIGNAL);
  437. if (bytes == 0) {
  438. //not an error reattempt.
  439. return true;
  440. }
  441. if (bytes < 0) {
  442. return false;
  443. }
  444. thread->read_pos = gator_buf_pos(thread->read_pos + bytes);
  445. }
  446. }
  447. if (write == (size_t) bytes && thread->oob_length > 0) {
  448. __sync_synchronize();
  449. /* Don't write more on a short write to be fair to other threads */
  450. bytes = send(thread->fd, thread->oob_data, thread->oob_length, MSG_NOSIGNAL);
  451. if (bytes == 0) {
  452. //not an error reattempt.
  453. return true;
  454. }
  455. if (bytes < 0) {
  456. return false;
  457. }
  458. thread->oob_data += bytes;
  459. thread->oob_length -= bytes;
  460. }
  461. return true;
  462. }
  463. static void * gator_func(void * arg)
  464. {
  465. bool print = true;
  466. uint64_t last = 0;
  467. prctl(PR_SET_NAME, (unsigned long) &"gator-annotate", 0, 0, 0);
  468. if (arg != NULL) {
  469. /* Forked */
  470. if (gator_state.parent_fd >= 0) {
  471. close(gator_state.parent_fd);
  472. gator_state.parent_fd = -1;
  473. }
  474. }
  475. for (;;) {
  476. if (gator_state.parent_fd < 0) {
  477. if (gator_parent_connect()) {
  478. /* Optimistically begin capturing data */
  479. gator_start_capturing();
  480. }
  481. else {
  482. gator_stop_capturing();
  483. if (print) {
  484. LOG(LOG_ERROR,
  485. "Warning : Not connected to gatord, " //
  486. "the application will run normally but Streamline will not collect annotations. " //
  487. "To collect annotations, please verify you are running gatord 5.%i or later and that SELinux " //
  488. "is disabled.\n", //
  489. gator_minimum_version);
  490. print = false;
  491. }
  492. sleep(1);
  493. continue;
  494. }
  495. }
  496. if (!gator_state.capturing) {
  497. char temp;
  498. const ssize_t bytes = read(gator_state.parent_fd, &temp, sizeof(temp));
  499. if (bytes <= 0) {
  500. close(gator_state.parent_fd);
  501. gator_state.parent_fd = -1;
  502. continue;
  503. }
  504. gator_start_capturing();
  505. gator_state.resend_state = true;
  506. }
  507. if (gator_state.capturing) {
  508. /* Iterate every 100ms */
  509. const uint64_t freq = NS_PER_S / 10;
  510. const uint64_t now = gator_time(CLOCK_REALTIME);
  511. const uint64_t wakeup = last + freq;
  512. if (wakeup < now) {
  513. /* Already timed out, save the current time and iterate again */
  514. last = now;
  515. }
  516. else {
  517. struct timespec ts;
  518. gator_set_ts(&ts, wakeup);
  519. sem_timedwait(&gator_state.sender_sem, &ts);
  520. last = wakeup;
  521. while (sem_trywait(&gator_state.sender_sem) == 0) {
  522. /* Ignore multiple posts */
  523. }
  524. }
  525. }
  526. int sync_count = 0;
  527. while (sem_trywait(&gator_state.sync_sem) == 0) {
  528. ++sync_count;
  529. }
  530. struct gator_thread ** prev = &gator_state.threads;
  531. struct gator_thread * thread = *prev;
  532. while (thread != NULL) {
  533. if (gator_state.capturing) {
  534. if (thread->fd < 0 && (thread->fd = gator_connect(thread->tid)) < 0) {
  535. gator_stop_capturing();
  536. }
  537. else {
  538. const uint32_t write_pos = thread->write_pos;
  539. if (write_pos != thread->read_pos || thread->oob_length > 0) {
  540. if (!gator_send(thread, write_pos)) {
  541. LOG(LOG_ERROR,
  542. "Failed to send bytes, " //
  543. "gator_thread = (exited:%s, fd:%d, oob_length:%zu, read_pos:%d, tid:%d), " //
  544. "write_pos = %u", //
  545. thread->exited ? "true" : "false",
  546. thread->fd,
  547. thread->oob_length,
  548. thread->read_pos,
  549. thread->tid,
  550. write_pos);
  551. gator_stop_capturing();
  552. }
  553. else {
  554. sem_post(&thread->sem);
  555. }
  556. }
  557. }
  558. }
  559. struct gator_thread * const next = thread->next;
  560. if (!thread->exited || !__sync_bool_compare_and_swap(prev, thread, next)) {
  561. /* If the cas fails, the linked list has changed, get it next time */
  562. prev = &thread->next;
  563. thread = *prev;
  564. }
  565. else {
  566. if (thread->fd > 0) {
  567. close(thread->fd);
  568. }
  569. sem_destroy(&thread->sem);
  570. free(thread);
  571. thread = next;
  572. }
  573. }
  574. for (; sync_count > 0; --sync_count) {
  575. sem_post(&gator_state.sync_waiter_sem);
  576. }
  577. }
  578. return NULL;
  579. }
  580. void gator_annotate_setup(void)
  581. {
  582. /* Support calling gator_annotate_setup more than once, but not at the same time on different cores */
  583. if (__sync_bool_compare_and_swap(&gator_state.initialized, false, true)) {
  584. gator_state.parent_fd = -1;
  585. /* Optimistically begin capturing data */
  586. gator_state.capturing = true;
  587. int err = sem_init(&gator_state.sender_sem, 0, 0);
  588. if (err != 0) {
  589. LOG(LOG_ERROR, "sem_init failed, with error %s", strerror(err));
  590. return;
  591. }
  592. err = sem_init(&gator_state.sync_sem, 0, 0);
  593. if (err != 0) {
  594. LOG(LOG_ERROR, "sem_init failed, with error %s", strerror(err));
  595. return;
  596. }
  597. err = sem_init(&gator_state.sync_waiter_sem, 0, 0);
  598. if (err != 0) {
  599. LOG(LOG_ERROR, "sem_init failed, with error %s", strerror(err));
  600. return;
  601. }
  602. err = pthread_key_create(&gator_state.key, gator_destructor);
  603. if (err != 0) {
  604. LOG(LOG_ERROR, "pthread_key_create failed, with error %s", strerror(err));
  605. return;
  606. }
  607. #if !defined(__ANDROID_API__) || __ANDROID_API__ >= 21
  608. err = pthread_atfork(NULL, NULL, gator_annotate_fork_child);
  609. if (err != 0) {
  610. LOG(LOG_ERROR, "pthread_atfork failed, with error %s", strerror(err));
  611. return;
  612. }
  613. #endif
  614. if (atexit(gator_annotate_flush) != 0) {
  615. LOG(LOG_ERROR, "atexit failed");
  616. return;
  617. }
  618. pthread_t thread;
  619. err = pthread_create(&thread, NULL, gator_func, NULL);
  620. if (err != 0) {
  621. LOG(LOG_ERROR, "pthread_create failed, with error %s", strerror(err));
  622. return;
  623. }
  624. }
  625. }
  626. static void gator_annotate_write_counter(struct gator_thread * thread, const struct gator_counter * counter);
  627. static void gator_annotate_write_cam_track(struct gator_thread * thread, const struct gator_cam_track * cam_track);
  628. static void gator_annotate_write_cam_name(struct gator_thread * thread, const struct gator_cam_name * cam_name);
  629. static struct gator_thread * gator_get_thread(void)
  630. {
  631. if (__sync_bool_compare_and_swap(&gator_state.forked, true, false)) {
  632. pthread_t thread;
  633. int err = pthread_create(&thread, NULL, gator_func, (void *) 1);
  634. if (err != 0) {
  635. LOG(LOG_ERROR, "pthread_create failed, with error %s", strerror(err));
  636. return NULL;
  637. }
  638. }
  639. if (!gator_state.capturing) {
  640. return NULL;
  641. }
  642. struct gator_thread * thread = (struct gator_thread *) pthread_getspecific(gator_state.key);
  643. int err;
  644. if (thread != NULL) {
  645. goto success;
  646. }
  647. thread = (struct gator_thread *) malloc(sizeof(*thread));
  648. if (thread == NULL) {
  649. LOG(LOG_ERROR, "malloc failed, with error %s", strerror(errno));
  650. return NULL;
  651. }
  652. thread->oob_data = NULL;
  653. thread->oob_length = 0;
  654. thread->fd = -1;
  655. thread->tid = syscall(__NR_gettid);
  656. thread->write_pos = 0;
  657. thread->read_pos = 0;
  658. thread->exited = false;
  659. err = sem_init(&thread->sem, 0, 0);
  660. if (err != 0) {
  661. LOG(LOG_ERROR, "sem_init failed, with error %s", strerror(err));
  662. goto fail_free_thread;
  663. }
  664. err = pthread_setspecific(gator_state.key, thread);
  665. if (err != 0) {
  666. LOG(LOG_ERROR, "pthread_setspecific failed, with error %s", strerror(err));
  667. goto fail_sem_destroy;
  668. }
  669. do {
  670. thread->next = gator_state.threads;
  671. } while (!__sync_bool_compare_and_swap(&gator_state.threads, thread->next, thread));
  672. success:
  673. if (__sync_bool_compare_and_swap(&gator_state.resend_state, true, false)) {
  674. struct gator_counter * counter;
  675. for (counter = gator_state.counters; counter != NULL; counter = counter->next) {
  676. gator_annotate_write_counter(thread, counter);
  677. }
  678. struct gator_cam_track * cam_track;
  679. for (cam_track = gator_state.cam_tracks; cam_track != NULL; cam_track = cam_track->next) {
  680. gator_annotate_write_cam_track(thread, cam_track);
  681. }
  682. struct gator_cam_name * cam_name;
  683. for (cam_name = gator_state.cam_names; cam_name != NULL; cam_name = cam_name->next) {
  684. gator_annotate_write_cam_name(thread, cam_name);
  685. }
  686. }
  687. return thread;
  688. fail_sem_destroy:
  689. sem_destroy(&thread->sem);
  690. fail_free_thread:
  691. free(thread);
  692. return NULL;
  693. }
  694. static uint32_t gator_buf_free(const struct gator_thread * const thread)
  695. {
  696. return (thread->read_pos - thread->write_pos - 1) & THREAD_BUFFER_MASK;
  697. }
  698. static uint32_t gator_buf_used(const struct gator_thread * const thread)
  699. {
  700. return (thread->write_pos - thread->read_pos) & THREAD_BUFFER_MASK;
  701. }
  702. #define gator_buf_wait_bytes(thread, bytes) \
  703. const uint32_t __bytes = (bytes); \
  704. if (__bytes > THREAD_BUFFER_SIZE / 2) { \
  705. /* Large annotations won't fit in the buffer */ \
  706. LOG(LOG_ERROR, "message is too large"); \
  707. return; \
  708. } \
  709. __gator_buf_wait_bytes((thread), __bytes);
  710. static void __gator_buf_wait_bytes(struct gator_thread * const thread, const uint32_t bytes)
  711. {
  712. while (gator_buf_free(thread) < bytes) {
  713. sem_post(&gator_state.sender_sem);
  714. sem_wait(&thread->sem);
  715. }
  716. }
  717. static void gator_msg_begin(const char marker,
  718. struct gator_thread * const thread,
  719. uint32_t * const write_pos_ptr,
  720. uint32_t * const size_pos_ptr,
  721. uint32_t * const length_ptr)
  722. {
  723. *write_pos_ptr = thread->write_pos;
  724. gator_buf_write_byte(thread->buf, write_pos_ptr, marker);
  725. *size_pos_ptr = *write_pos_ptr;
  726. *write_pos_ptr = gator_buf_pos(*write_pos_ptr + sizeof(uint32_t));
  727. *length_ptr = 0;
  728. }
  729. static void gator_msg_end(struct gator_thread * const thread,
  730. const uint32_t write_pos,
  731. uint32_t size_pos,
  732. const uint32_t length)
  733. {
  734. gator_buf_write_uint32(thread->buf, &size_pos, length);
  735. thread->write_pos = write_pos;
  736. /* Wakeup the sender thread if 3/4 full */
  737. if (gator_buf_used(thread) >= 3 * THREAD_BUFFER_SIZE / 4) {
  738. sem_post(&gator_state.sender_sem);
  739. }
  740. }
  741. void gator_annotate_str(const uint32_t channel, const char * const str)
  742. {
  743. struct gator_thread * const thread = gator_get_thread();
  744. if (thread == NULL) {
  745. return;
  746. }
  747. const int str_size = (str == NULL) ? 0 : strlen(str);
  748. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_LONG + MAXSIZE_PACK_INT + str_size);
  749. uint32_t write_pos;
  750. uint32_t size_pos;
  751. uint32_t length;
  752. gator_msg_begin(HEADER_UTF8, thread, &write_pos, &size_pos, &length);
  753. length += gator_buf_write_time(thread->buf, &write_pos);
  754. length += gator_buf_write_int(thread->buf, &write_pos, channel);
  755. length += gator_buf_write_bytes(thread->buf, &write_pos, str, str_size);
  756. gator_msg_end(thread, write_pos, size_pos, length);
  757. }
  758. void gator_annotate_color(const uint32_t channel, const uint32_t color, const char * const str)
  759. {
  760. struct gator_thread * const thread = gator_get_thread();
  761. if (thread == NULL) {
  762. return;
  763. }
  764. const int str_size = (str == NULL) ? 0 : strlen(str);
  765. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_LONG + MAXSIZE_PACK_INT + SIZE_COLOR + str_size);
  766. uint32_t write_pos;
  767. uint32_t size_pos;
  768. uint32_t length;
  769. gator_msg_begin(HEADER_UTF8_COLOR, thread, &write_pos, &size_pos, &length);
  770. length += gator_buf_write_time(thread->buf, &write_pos);
  771. length += gator_buf_write_int(thread->buf, &write_pos, channel);
  772. length += gator_buf_write_color(thread->buf, &write_pos, color);
  773. length += gator_buf_write_bytes(thread->buf, &write_pos, str, str_size);
  774. gator_msg_end(thread, write_pos, size_pos, length);
  775. }
  776. void gator_annotate_name_channel(const uint32_t channel, const uint32_t group, const char * const str)
  777. {
  778. struct gator_thread * const thread = gator_get_thread();
  779. if (thread == NULL) {
  780. return;
  781. }
  782. const int str_size = (str == NULL) ? 0 : strlen(str);
  783. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_LONG + 2 * MAXSIZE_PACK_INT + str_size);
  784. uint32_t write_pos;
  785. uint32_t size_pos;
  786. uint32_t length;
  787. gator_msg_begin(HEADER_CHANNEL_NAME, thread, &write_pos, &size_pos, &length);
  788. length += gator_buf_write_time(thread->buf, &write_pos);
  789. length += gator_buf_write_int(thread->buf, &write_pos, channel);
  790. length += gator_buf_write_int(thread->buf, &write_pos, group);
  791. length += gator_buf_write_bytes(thread->buf, &write_pos, str, str_size);
  792. gator_msg_end(thread, write_pos, size_pos, length);
  793. }
  794. void gator_annotate_name_group(const uint32_t group, const char * const str)
  795. {
  796. struct gator_thread * const thread = gator_get_thread();
  797. if (thread == NULL) {
  798. return;
  799. }
  800. const int str_size = (str == NULL) ? 0 : strlen(str);
  801. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_LONG + MAXSIZE_PACK_INT + str_size);
  802. uint32_t write_pos;
  803. uint32_t size_pos;
  804. uint32_t length;
  805. gator_msg_begin(HEADER_GROUP_NAME, thread, &write_pos, &size_pos, &length);
  806. length += gator_buf_write_time(thread->buf, &write_pos);
  807. length += gator_buf_write_int(thread->buf, &write_pos, group);
  808. length += gator_buf_write_bytes(thread->buf, &write_pos, str, str_size);
  809. gator_msg_end(thread, write_pos, size_pos, length);
  810. }
  811. void gator_annotate_visual(const void * const data, const uint32_t data_length, const char * const str)
  812. {
  813. struct gator_thread * const thread = gator_get_thread();
  814. if (thread == NULL) {
  815. return;
  816. }
  817. const int str_size = (str == NULL) ? 0 : strlen(str);
  818. /* Don't include data_length because it doesn't end up in the buffer */
  819. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_LONG + str_size + 1);
  820. uint32_t write_pos;
  821. uint32_t size_pos;
  822. uint32_t length;
  823. gator_msg_begin(HEADER_VISUAL, thread, &write_pos, &size_pos, &length);
  824. length += gator_buf_write_time(thread->buf, &write_pos);
  825. length += gator_buf_write_bytes(thread->buf, &write_pos, str, str_size);
  826. length += gator_buf_write_byte(thread->buf, &write_pos, '\0');
  827. /* Calculate the length, but don't write the image */
  828. length += data_length;
  829. /* Write the length and commit the first part of the message */
  830. gator_buf_write_uint32(thread->buf, &size_pos, length);
  831. thread->write_pos = write_pos;
  832. thread->oob_data = (const char *) data;
  833. __sync_synchronize();
  834. thread->oob_length = data_length;
  835. while (thread->oob_length > 0) {
  836. sem_post(&gator_state.sender_sem);
  837. sem_wait(&thread->sem);
  838. }
  839. }
  840. void gator_annotate_marker(const char * const str)
  841. {
  842. struct gator_thread * const thread = gator_get_thread();
  843. if (thread == NULL) {
  844. return;
  845. }
  846. const int str_size = (str == NULL) ? 0 : strlen(str);
  847. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_LONG + str_size);
  848. uint32_t write_pos;
  849. uint32_t size_pos;
  850. uint32_t length;
  851. gator_msg_begin(HEADER_MARKER, thread, &write_pos, &size_pos, &length);
  852. length += gator_buf_write_time(thread->buf, &write_pos);
  853. length += gator_buf_write_bytes(thread->buf, &write_pos, str, str_size);
  854. gator_msg_end(thread, write_pos, size_pos, length);
  855. }
  856. void gator_annotate_marker_color(const uint32_t color, const char * const str)
  857. {
  858. struct gator_thread * const thread = gator_get_thread();
  859. if (thread == NULL) {
  860. return;
  861. }
  862. const int str_size = (str == NULL) ? 0 : strlen(str);
  863. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_LONG + SIZE_COLOR + str_size);
  864. uint32_t write_pos;
  865. uint32_t size_pos;
  866. uint32_t length;
  867. gator_msg_begin(HEADER_MARKER_COLOR, thread, &write_pos, &size_pos, &length);
  868. length += gator_buf_write_time(thread->buf, &write_pos);
  869. length += gator_buf_write_color(thread->buf, &write_pos, color);
  870. length += gator_buf_write_bytes(thread->buf, &write_pos, str, str_size);
  871. gator_msg_end(thread, write_pos, size_pos, length);
  872. }
  873. static void gator_annotate_write_counter(struct gator_thread * const thread, const struct gator_counter * const counter)
  874. {
  875. const int title_size = (counter->title == NULL) ? 0 : strlen(counter->title);
  876. const int name_size = (counter->name == NULL) ? 0 : strlen(counter->name);
  877. const int units_size = (counter->units == NULL) ? 0 : strlen(counter->units);
  878. const int description_size = (counter->description == NULL) ? 0 : strlen(counter->description);
  879. int activity_size = 0;
  880. size_t i;
  881. for (i = 0; i < counter->activity_count; ++i) {
  882. activity_size += (counter->activities[i] == NULL) ? 0 : strlen(counter->activities[i]);
  883. activity_size += SIZE_COLOR;
  884. }
  885. gator_buf_wait_bytes(thread,
  886. 1 + sizeof(uint32_t) + 12 * MAXSIZE_PACK_INT + SIZE_COLOR + activity_size + title_size + 1 +
  887. name_size + 1 + units_size + 1 + description_size);
  888. uint32_t write_pos;
  889. uint32_t size_pos;
  890. uint32_t length;
  891. gator_msg_begin(HEADER_COUNTER, thread, &write_pos, &size_pos, &length);
  892. length += gator_buf_write_int(thread->buf, &write_pos, counter->id);
  893. length += gator_buf_write_int(thread->buf, &write_pos, counter->per_cpu);
  894. length += gator_buf_write_int(thread->buf, &write_pos, counter->counter_class);
  895. length += gator_buf_write_int(thread->buf, &write_pos, counter->display);
  896. length += gator_buf_write_int(thread->buf, &write_pos, counter->modifier);
  897. length += gator_buf_write_int(thread->buf, &write_pos, counter->series_composition);
  898. length += gator_buf_write_int(thread->buf, &write_pos, counter->rendering_type);
  899. length += gator_buf_write_int(thread->buf, &write_pos, counter->average_selection);
  900. length += gator_buf_write_int(thread->buf, &write_pos, counter->average_cores);
  901. length += gator_buf_write_int(thread->buf, &write_pos, counter->percentage);
  902. length += gator_buf_write_int(thread->buf, &write_pos, counter->activity_count);
  903. length += gator_buf_write_int(thread->buf, &write_pos, counter->cores);
  904. length += gator_buf_write_color(thread->buf, &write_pos, counter->color);
  905. for (i = 0; i < counter->activity_count; ++i) {
  906. length += gator_buf_write_bytes(thread->buf,
  907. &write_pos,
  908. counter->activities[i],
  909. (counter->activities[i] == NULL) ? 0 : strlen(counter->activities[i]));
  910. length += gator_buf_write_byte(thread->buf, &write_pos, '\0');
  911. length += gator_buf_write_color(thread->buf, &write_pos, counter->activity_colors[i]);
  912. }
  913. length += gator_buf_write_bytes(thread->buf, &write_pos, counter->title, title_size);
  914. length += gator_buf_write_byte(thread->buf, &write_pos, '\0');
  915. length += gator_buf_write_bytes(thread->buf, &write_pos, counter->name, name_size);
  916. length += gator_buf_write_byte(thread->buf, &write_pos, '\0');
  917. length += gator_buf_write_bytes(thread->buf, &write_pos, counter->units, units_size);
  918. length += gator_buf_write_byte(thread->buf, &write_pos, '\0');
  919. length += gator_buf_write_bytes(thread->buf, &write_pos, counter->description, description_size);
  920. gator_msg_end(thread, write_pos, size_pos, length);
  921. }
  922. void gator_annotate_counter(const uint32_t id,
  923. const char * const title,
  924. const char * const name,
  925. const int per_cpu,
  926. const enum gator_annotate_counter_class counter_class,
  927. const enum gator_annotate_display display,
  928. const char * const units,
  929. const uint32_t modifier,
  930. const enum gator_annotate_series_composition series_composition,
  931. const enum gator_annotate_rendering_type rendering_type,
  932. const int average_selection,
  933. const int average_cores,
  934. const int percentage,
  935. const size_t activity_count,
  936. const char * const * const activities,
  937. const uint32_t * const activity_colors,
  938. const uint32_t cores,
  939. const uint32_t color,
  940. const char * const description)
  941. {
  942. struct gator_counter * const counter = (struct gator_counter *) malloc(sizeof(*counter));
  943. if (counter == NULL) {
  944. LOG(LOG_ERROR, "malloc failed, with error %s", strerror(errno));
  945. return;
  946. }
  947. /* Save off this counter so it can be resent if needed */
  948. counter->id = id;
  949. counter->title = (title == NULL) ? NULL : strdup(title);
  950. counter->name = (name == NULL) ? NULL : strdup(name);
  951. counter->per_cpu = per_cpu;
  952. counter->counter_class = counter_class;
  953. counter->display = display;
  954. counter->units = (units == NULL) ? NULL : strdup(units);
  955. counter->modifier = modifier;
  956. counter->series_composition = series_composition;
  957. counter->rendering_type = rendering_type;
  958. counter->average_selection = average_selection;
  959. counter->average_cores = average_cores;
  960. counter->percentage = percentage;
  961. counter->activity_count = activity_count;
  962. if (activity_count == 0) {
  963. counter->activities = NULL;
  964. counter->activity_colors = NULL;
  965. }
  966. else {
  967. counter->activities = (const char **) malloc(activity_count * sizeof(activities[0]));
  968. if (counter->activities == NULL) {
  969. LOG(LOG_ERROR, "malloc failed, with error %s", strerror(errno));
  970. goto free_counter;
  971. }
  972. counter->activity_colors = (uint32_t *) malloc(activity_count * sizeof(activity_colors[0]));
  973. if (counter->activity_colors == NULL) {
  974. LOG(LOG_ERROR, "malloc failed, with error %s", strerror(errno));
  975. goto free_activities;
  976. }
  977. size_t i;
  978. for (i = 0; i < activity_count; ++i) {
  979. counter->activities[i] = (activities[i] == NULL) ? NULL : strdup(activities[i]);
  980. counter->activity_colors[i] = activity_colors[i];
  981. }
  982. }
  983. counter->cores = cores;
  984. counter->color = color;
  985. counter->description = (description == NULL) ? NULL : strdup(description);
  986. do {
  987. counter->next = gator_state.counters;
  988. } while (!__sync_bool_compare_and_swap(&gator_state.counters, counter->next, counter));
  989. {
  990. struct gator_thread * const thread = gator_get_thread();
  991. if (thread == NULL) {
  992. return;
  993. }
  994. gator_annotate_write_counter(thread, counter);
  995. }
  996. return;
  997. free_activities:
  998. free(counter->activities);
  999. free_counter:
  1000. free(counter);
  1001. }
  1002. // NOLINTNEXTLINE(bugprone-easily-swappable-parameters, readability-identifier-length)
  1003. void gator_annotate_counter_time_value(const uint32_t core, const uint32_t id, const uint64_t time, const int64_t value)
  1004. {
  1005. struct gator_thread * const thread = gator_get_thread();
  1006. if (thread == NULL) {
  1007. return;
  1008. }
  1009. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + 2 * MAXSIZE_PACK_LONG + 2 * MAXSIZE_PACK_INT);
  1010. uint32_t write_pos;
  1011. uint32_t size_pos;
  1012. uint32_t length;
  1013. gator_msg_begin(HEADER_COUNTER_VALUE, thread, &write_pos, &size_pos, &length);
  1014. // NOLINTNEXTLINE(bugprone-narrowing-conversions)
  1015. length += gator_buf_write_long(thread->buf, &write_pos, time);
  1016. length += gator_buf_write_int(thread->buf, &write_pos, core);
  1017. length += gator_buf_write_int(thread->buf, &write_pos, id);
  1018. length += gator_buf_write_long(thread->buf, &write_pos, value);
  1019. gator_msg_end(thread, write_pos, size_pos, length);
  1020. }
  1021. // NOLINTNEXTLINE(readability-identifier-length)
  1022. void gator_annotate_counter_value(const uint32_t core, const uint32_t id, const int64_t value)
  1023. {
  1024. const uint64_t current_time = gator_get_time();
  1025. gator_annotate_counter_time_value(core, id, current_time, value);
  1026. }
  1027. // NOLINTNEXTLINE(readability-identifier-length)
  1028. void gator_annotate_activity_switch(const uint32_t core, const uint32_t id, const uint32_t activity, const uint32_t tid)
  1029. {
  1030. struct gator_thread * const thread = gator_get_thread();
  1031. if (thread == NULL) {
  1032. return;
  1033. }
  1034. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_LONG + 4 * MAXSIZE_PACK_INT);
  1035. uint32_t write_pos;
  1036. uint32_t size_pos;
  1037. uint32_t length;
  1038. gator_msg_begin(HEADER_ACTIVITY_SWITCH, thread, &write_pos, &size_pos, &length);
  1039. length += gator_buf_write_time(thread->buf, &write_pos);
  1040. length += gator_buf_write_int(thread->buf, &write_pos, core);
  1041. length += gator_buf_write_int(thread->buf, &write_pos, id);
  1042. length += gator_buf_write_int(thread->buf, &write_pos, activity);
  1043. length += gator_buf_write_int(thread->buf, &write_pos, tid);
  1044. gator_msg_end(thread, write_pos, size_pos, length);
  1045. }
  1046. static void gator_annotate_write_cam_track(struct gator_thread * const thread,
  1047. const struct gator_cam_track * const cam_track)
  1048. {
  1049. const int name_size = (cam_track->name == NULL) ? 0 : strlen(cam_track->name);
  1050. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + 3 * MAXSIZE_PACK_INT + name_size);
  1051. uint32_t write_pos;
  1052. uint32_t size_pos;
  1053. uint32_t length;
  1054. gator_msg_begin(HEADER_CAM_TRACK, thread, &write_pos, &size_pos, &length);
  1055. length += gator_buf_write_int(thread->buf, &write_pos, cam_track->view_uid);
  1056. length += gator_buf_write_int(thread->buf, &write_pos, cam_track->track_uid);
  1057. length += gator_buf_write_int(thread->buf, &write_pos, cam_track->parent_track);
  1058. length += gator_buf_write_bytes(thread->buf, &write_pos, cam_track->name, name_size);
  1059. gator_msg_end(thread, write_pos, size_pos, length);
  1060. }
  1061. void gator_cam_track(const uint32_t view_uid,
  1062. const uint32_t track_uid,
  1063. const uint32_t parent_track,
  1064. const char * const name)
  1065. {
  1066. struct gator_cam_track * const cam_track = (struct gator_cam_track *) malloc(sizeof(*cam_track));
  1067. if (cam_track == NULL) {
  1068. LOG(LOG_ERROR, "malloc failed, with error %s", strerror(errno));
  1069. return;
  1070. }
  1071. /* Save off this track so it can be resent if needed */
  1072. cam_track->view_uid = view_uid;
  1073. cam_track->track_uid = track_uid;
  1074. cam_track->parent_track = parent_track;
  1075. cam_track->name = (name == NULL) ? NULL : strdup(name);
  1076. do {
  1077. cam_track->next = gator_state.cam_tracks;
  1078. } while (!__sync_bool_compare_and_swap(&gator_state.cam_tracks, cam_track->next, cam_track));
  1079. struct gator_thread * const thread = gator_get_thread();
  1080. if (thread == NULL) {
  1081. return;
  1082. }
  1083. gator_annotate_write_cam_track(thread, cam_track);
  1084. }
  1085. void gator_cam_job(const uint32_t view_uid,
  1086. const uint32_t job_uid,
  1087. const char * const name,
  1088. const uint32_t track,
  1089. const uint64_t start_time,
  1090. const uint64_t duration,
  1091. const uint32_t color,
  1092. const uint32_t primary_dependency,
  1093. const size_t dependency_count,
  1094. const uint32_t * const dependencies)
  1095. {
  1096. struct gator_thread * const thread = gator_get_thread();
  1097. if (thread == NULL) {
  1098. return;
  1099. }
  1100. const int name_size = (name == NULL) ? 0 : strlen(name);
  1101. gator_buf_wait_bytes(thread,
  1102. 1 + sizeof(uint32_t) + 5 * MAXSIZE_PACK_INT + 2 * MAXSIZE_PACK_LONG + SIZE_COLOR +
  1103. dependency_count * MAXSIZE_PACK_INT + name_size);
  1104. uint32_t write_pos;
  1105. uint32_t size_pos;
  1106. uint32_t length;
  1107. gator_msg_begin(HEADER_CAM_JOB, thread, &write_pos, &size_pos, &length);
  1108. length += gator_buf_write_int(thread->buf, &write_pos, view_uid);
  1109. length += gator_buf_write_int(thread->buf, &write_pos, job_uid);
  1110. length += gator_buf_write_int(thread->buf, &write_pos, track);
  1111. length += gator_buf_write_long(thread->buf, &write_pos, start_time);
  1112. length += gator_buf_write_long(thread->buf, &write_pos, duration);
  1113. length += gator_buf_write_color(thread->buf, &write_pos, color);
  1114. // NOLINTNEXTLINE(bugprone-narrowing-conversions)
  1115. length += gator_buf_write_int(thread->buf, &write_pos, primary_dependency);
  1116. length += gator_buf_write_int(thread->buf, &write_pos, dependency_count);
  1117. size_t i;
  1118. for (i = 0; i < dependency_count; ++i) {
  1119. length += gator_buf_write_int(thread->buf, &write_pos, dependencies[i]);
  1120. }
  1121. length += gator_buf_write_bytes(thread->buf, &write_pos, name, name_size);
  1122. gator_msg_end(thread, write_pos, size_pos, length);
  1123. }
  1124. void gator_cam_job_start(const uint32_t view_uid,
  1125. const uint32_t job_uid,
  1126. const char * const name,
  1127. const uint32_t track,
  1128. const uint64_t time,
  1129. const uint32_t color)
  1130. {
  1131. struct gator_thread * const thread = gator_get_thread();
  1132. if (thread == NULL) {
  1133. return;
  1134. }
  1135. const int name_size = (name == NULL) ? 0 : strlen(name);
  1136. gator_buf_wait_bytes(thread,
  1137. 1 + sizeof(uint32_t) + 3 * MAXSIZE_PACK_INT + MAXSIZE_PACK_LONG + SIZE_COLOR + name_size);
  1138. uint32_t write_pos;
  1139. uint32_t size_pos;
  1140. uint32_t length;
  1141. gator_msg_begin(HEADER_CAM_JOB_START, thread, &write_pos, &size_pos, &length);
  1142. length += gator_buf_write_int(thread->buf, &write_pos, view_uid);
  1143. length += gator_buf_write_int(thread->buf, &write_pos, job_uid);
  1144. length += gator_buf_write_int(thread->buf, &write_pos, track);
  1145. length += gator_buf_write_long(thread->buf, &write_pos, time);
  1146. length += gator_buf_write_color(thread->buf, &write_pos, color);
  1147. length += gator_buf_write_bytes(thread->buf, &write_pos, name, name_size);
  1148. gator_msg_end(thread, write_pos, size_pos, length);
  1149. }
  1150. void gator_cam_job_set_dependencies(const uint32_t view_uid,
  1151. const uint32_t job_uid,
  1152. const uint64_t time,
  1153. const uint32_t primary_dependency,
  1154. const size_t dependency_count,
  1155. const uint32_t * const dependencies)
  1156. {
  1157. struct gator_thread * const thread = gator_get_thread();
  1158. if (thread == NULL) {
  1159. return;
  1160. }
  1161. gator_buf_wait_bytes(thread,
  1162. 1 + sizeof(uint32_t) + 4 * MAXSIZE_PACK_INT + MAXSIZE_PACK_LONG +
  1163. dependency_count * MAXSIZE_PACK_INT);
  1164. uint32_t write_pos;
  1165. uint32_t size_pos;
  1166. uint32_t length;
  1167. gator_msg_begin(HEADER_CAM_JOB_SET_DEPS, thread, &write_pos, &size_pos, &length);
  1168. length += gator_buf_write_int(thread->buf, &write_pos, view_uid);
  1169. length += gator_buf_write_int(thread->buf, &write_pos, job_uid);
  1170. length += gator_buf_write_long(thread->buf, &write_pos, time);
  1171. length += gator_buf_write_int(thread->buf, &write_pos, primary_dependency);
  1172. length += gator_buf_write_int(thread->buf, &write_pos, dependency_count);
  1173. size_t i;
  1174. for (i = 0; i < dependency_count; ++i) {
  1175. length += gator_buf_write_int(thread->buf, &write_pos, dependencies[i]);
  1176. }
  1177. gator_msg_end(thread, write_pos, size_pos, length);
  1178. }
  1179. void gator_cam_job_stop(const uint32_t view_uid, const uint32_t job_uid, const uint64_t time)
  1180. {
  1181. struct gator_thread * const thread = gator_get_thread();
  1182. if (thread == NULL) {
  1183. return;
  1184. }
  1185. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + 2 * MAXSIZE_PACK_INT + MAXSIZE_PACK_LONG);
  1186. uint32_t write_pos;
  1187. uint32_t size_pos;
  1188. uint32_t length;
  1189. gator_msg_begin(HEADER_CAM_JOB_STOP, thread, &write_pos, &size_pos, &length);
  1190. length += gator_buf_write_int(thread->buf, &write_pos, view_uid);
  1191. length += gator_buf_write_int(thread->buf, &write_pos, job_uid);
  1192. length += gator_buf_write_long(thread->buf, &write_pos, time);
  1193. gator_msg_end(thread, write_pos, size_pos, length);
  1194. }
  1195. static void gator_annotate_write_cam_name(struct gator_thread * const thread,
  1196. const struct gator_cam_name * const cam_name)
  1197. {
  1198. const int name_size = (cam_name->name == NULL) ? 0 : strlen(cam_name->name);
  1199. gator_buf_wait_bytes(thread, 1 + sizeof(uint32_t) + MAXSIZE_PACK_INT + name_size);
  1200. uint32_t write_pos;
  1201. uint32_t size_pos;
  1202. uint32_t length;
  1203. gator_msg_begin(HEADER_CAM_VIEW_NAME, thread, &write_pos, &size_pos, &length);
  1204. length += gator_buf_write_int(thread->buf, &write_pos, cam_name->view_uid);
  1205. length += gator_buf_write_bytes(thread->buf, &write_pos, cam_name->name, name_size);
  1206. gator_msg_end(thread, write_pos, size_pos, length);
  1207. }
  1208. void gator_cam_view_name(const uint32_t view_uid, const char * const name)
  1209. {
  1210. struct gator_cam_name * const cam_name = (struct gator_cam_name *) malloc(sizeof(*cam_name));
  1211. if (cam_name == NULL) {
  1212. return;
  1213. }
  1214. /* Save off this name so it can be resent if needed */
  1215. cam_name->next = NULL;
  1216. cam_name->view_uid = view_uid;
  1217. cam_name->name = (name == NULL) ? NULL : strdup(name);
  1218. do {
  1219. cam_name->next = gator_state.cam_names;
  1220. } while (!__sync_bool_compare_and_swap(&gator_state.cam_names, cam_name->next, cam_name));
  1221. struct gator_thread * const thread = gator_get_thread();
  1222. if (thread == NULL) {
  1223. return;
  1224. }
  1225. gator_annotate_write_cam_name(thread, cam_name);
  1226. }