coroipc_ipc.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*
  2. * Copyright (c) 2009 Red Hat, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Steven Dake (sdake@redhat.com)
  7. *
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #ifndef COROIPC_IPC_H_DEFINED
  35. #define COROIPC_IPC_H_DEFINED
  36. #include <unistd.h>
  37. #include <poll.h>
  38. #include <time.h>
  39. #include "corotypes.h"
  40. #include "config.h"
  41. /*
  42. * Darwin claims to support process shared synchronization
  43. * but it really does not. The unistd.h header file is wrong.
  44. */
  45. #if defined(COROSYNC_DARWIN) || defined(__UCLIBC__)
  46. #undef _POSIX_THREAD_PROCESS_SHARED
  47. #define _POSIX_THREAD_PROCESS_SHARED -1
  48. #endif
  49. #ifndef _POSIX_THREAD_PROCESS_SHARED
  50. #define _POSIX_THREAD_PROCESS_SHARED -1
  51. #endif
  52. #if _POSIX_THREAD_PROCESS_SHARED > 0
  53. #include <semaphore.h>
  54. #else
  55. #include <sys/sem.h>
  56. #if defined(_SEM_SEMUN_UNDEFINED)
  57. union semun {
  58. int val;
  59. struct semid_ds *buf;
  60. unsigned short int *array;
  61. struct seminfo *__buf;
  62. };
  63. #endif
  64. #endif
  65. /*
  66. * Define sem_wait timeout (real timeout will be (n-1;n) )
  67. */
  68. #define IPC_SEMWAIT_TIMEOUT 2
  69. #define IPC_SEMWAIT_NOFILE 0
  70. enum req_init_types {
  71. MESSAGE_REQ_RESPONSE_INIT = 0,
  72. MESSAGE_REQ_DISPATCH_INIT = 1
  73. };
  74. #define MESSAGE_REQ_CHANGE_EUID 1
  75. enum ipc_semaphore_identifiers {
  76. SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT = 0,
  77. SEMAPHORE_REQUEST = 1,
  78. SEMAPHORE_RESPONSE = 2,
  79. SEMAPHORE_DISPATCH = 3
  80. };
  81. struct control_buffer {
  82. unsigned int read;
  83. unsigned int write;
  84. int flow_control_enabled;
  85. #if _POSIX_THREAD_PROCESS_SHARED > 0
  86. sem_t sem_request_or_flush_or_exit;
  87. sem_t sem_response;
  88. sem_t sem_dispatch;
  89. sem_t sem_request;
  90. #else
  91. int semid;
  92. #endif
  93. int ipc_closed;
  94. };
  95. enum res_init_types {
  96. MESSAGE_RES_INIT
  97. };
  98. typedef struct {
  99. int service __attribute__((aligned(8)));
  100. unsigned long long semkey __attribute__((aligned(8)));
  101. char control_file[PATH_MAX] __attribute__((aligned(8)));
  102. char request_file[PATH_MAX] __attribute__((aligned(8)));
  103. char response_file[PATH_MAX] __attribute__((aligned(8)));
  104. char dispatch_file[PATH_MAX] __attribute__((aligned(8)));
  105. size_t control_size __attribute__((aligned(8)));
  106. size_t request_size __attribute__((aligned(8)));
  107. size_t response_size __attribute__((aligned(8)));
  108. size_t dispatch_size __attribute__((aligned(8)));
  109. } mar_req_setup_t __attribute__((aligned(8)));
  110. typedef struct {
  111. int error __attribute__((aligned(8)));
  112. } mar_res_setup_t __attribute__((aligned(8)));
  113. typedef struct {
  114. uid_t euid __attribute__((aligned(8)));
  115. gid_t egid __attribute__((aligned(8)));
  116. } mar_req_priv_change __attribute__((aligned(8)));
  117. typedef struct {
  118. coroipc_response_header_t header __attribute__((aligned(8)));
  119. uint64_t conn_info __attribute__((aligned(8)));
  120. } mar_res_lib_response_init_t __attribute__((aligned(8)));
  121. typedef struct {
  122. coroipc_response_header_t header __attribute__((aligned(8)));
  123. } mar_res_lib_dispatch_init_t __attribute__((aligned(8)));
  124. typedef struct {
  125. uint32_t nodeid __attribute__((aligned(8)));
  126. void *conn __attribute__((aligned(8)));
  127. } mar_message_source_t __attribute__((aligned(8)));
  128. typedef struct {
  129. coroipc_request_header_t header __attribute__((aligned(8)));
  130. size_t map_size __attribute__((aligned(8)));
  131. char path_to_file[128] __attribute__((aligned(8)));
  132. } mar_req_coroipcc_zc_alloc_t __attribute__((aligned(8)));
  133. typedef struct {
  134. coroipc_request_header_t header __attribute__((aligned(8)));
  135. size_t map_size __attribute__((aligned(8)));
  136. uint64_t server_address __attribute__((aligned(8)));
  137. } mar_req_coroipcc_zc_free_t __attribute__((aligned(8)));
  138. typedef struct {
  139. coroipc_request_header_t header __attribute__((aligned(8)));
  140. uint64_t server_address __attribute__((aligned(8)));
  141. } mar_req_coroipcc_zc_execute_t __attribute__((aligned(8)));
  142. struct coroipcs_zc_header {
  143. int map_size;
  144. uint64_t server_address;
  145. };
  146. #define SOCKET_SERVICE_INIT 0xFFFFFFFF
  147. #define SOCKET_SERVICE_SECURITY_VIOLATION 0xFFFFFFFE
  148. #define ZC_ALLOC_HEADER 0xFFFFFFFF
  149. #define ZC_FREE_HEADER 0xFFFFFFFE
  150. #define ZC_EXECUTE_HEADER 0xFFFFFFFD
  151. static inline cs_error_t
  152. ipc_sem_wait (
  153. struct control_buffer *control_buffer,
  154. enum ipc_semaphore_identifiers sem_id,
  155. int fd)
  156. {
  157. #if _POSIX_THREAD_PROCESS_SHARED < 1
  158. struct sembuf sop;
  159. #else
  160. struct timespec timeout;
  161. struct pollfd pfd;
  162. sem_t *sem = NULL;
  163. #endif
  164. int res;
  165. #if _POSIX_THREAD_PROCESS_SHARED > 0
  166. switch (sem_id) {
  167. case SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT:
  168. sem = &control_buffer->sem_request_or_flush_or_exit;
  169. break;
  170. case SEMAPHORE_RESPONSE:
  171. sem = &control_buffer->sem_request;
  172. break;
  173. case SEMAPHORE_DISPATCH:
  174. sem = &control_buffer->sem_response;
  175. break;
  176. case SEMAPHORE_REQUEST:
  177. sem = &control_buffer->sem_dispatch;
  178. break;
  179. }
  180. if (fd == IPC_SEMWAIT_NOFILE) {
  181. retry_sem_wait:
  182. res = sem_wait (sem);
  183. if (res == -1 && errno == EINTR) {
  184. goto retry_sem_wait;
  185. } else
  186. if (res == -1) {
  187. return (CS_ERR_LIBRARY);
  188. }
  189. } else {
  190. if (control_buffer->ipc_closed) {
  191. return (CS_ERR_LIBRARY);
  192. }
  193. timeout.tv_sec = time(NULL) + IPC_SEMWAIT_TIMEOUT;
  194. timeout.tv_nsec = 0;
  195. retry_sem_timedwait:
  196. res = sem_timedwait (sem, &timeout);
  197. if (res == -1 && errno == ETIMEDOUT) {
  198. pfd.fd = fd;
  199. pfd.events = 0;
  200. /*
  201. * Determine if server has failed (ERR_LIBRARY) or
  202. * is just performing slowly or in configuration change
  203. * (retry sem op)
  204. */
  205. retry_poll:
  206. res = poll (&pfd, 1, 0);
  207. if (res == -1 && errno == EINTR) {
  208. goto retry_poll;
  209. } else
  210. if (res == -1) {
  211. return (CS_ERR_LIBRARY);
  212. }
  213. if (res == 1) {
  214. if (pfd.revents == POLLERR ||
  215. pfd.revents == POLLHUP ||
  216. pfd.revents == POLLNVAL) {
  217. return (CS_ERR_LIBRARY);
  218. }
  219. }
  220. goto retry_sem_timedwait;
  221. } else
  222. if (res == -1 && errno == EINTR) {
  223. goto retry_sem_timedwait;
  224. } else
  225. if (res == -1) {
  226. return (CS_ERR_LIBRARY);
  227. }
  228. if (res == 0 && control_buffer->ipc_closed) {
  229. return (CS_ERR_LIBRARY);
  230. }
  231. }
  232. #else
  233. sop.sem_num = sem_id;
  234. sop.sem_op = -1;
  235. sop.sem_flg = 0;
  236. retry_semop:
  237. res = semop (control_buffer->semid, &sop, 1);
  238. if (res == -1 && errno == EINTR) {
  239. return (CS_ERR_TRY_AGAIN);
  240. goto retry_semop;
  241. } else
  242. if (res == -1 && errno == EACCES) {
  243. return (CS_ERR_TRY_AGAIN);
  244. } else
  245. if (res == -1) {
  246. return (CS_ERR_LIBRARY);
  247. }
  248. #endif
  249. return (CS_OK);
  250. }
  251. static inline cs_error_t
  252. ipc_sem_post (
  253. struct control_buffer *control_buffer,
  254. enum ipc_semaphore_identifiers sem_id)
  255. {
  256. #if _POSIX_THREAD_PROCESS_SHARED < 1
  257. struct sembuf sop;
  258. #else
  259. sem_t *sem = NULL;
  260. #endif
  261. int res;
  262. #if _POSIX_THREAD_PROCESS_SHARED > 0
  263. switch (sem_id) {
  264. case SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT:
  265. sem = &control_buffer->sem_request_or_flush_or_exit;
  266. break;
  267. case SEMAPHORE_RESPONSE:
  268. sem = &control_buffer->sem_request;
  269. break;
  270. case SEMAPHORE_DISPATCH:
  271. sem = &control_buffer->sem_response;
  272. break;
  273. case SEMAPHORE_REQUEST:
  274. sem = &control_buffer->sem_dispatch;
  275. break;
  276. }
  277. res = sem_post (sem);
  278. if (res == -1) {
  279. return (CS_ERR_LIBRARY);
  280. }
  281. #else
  282. sop.sem_num = sem_id;
  283. sop.sem_op = 1;
  284. sop.sem_flg = 0;
  285. retry_semop:
  286. res = semop (control_buffer->semid, &sop, 1);
  287. if (res == -1 && errno == EINTR) {
  288. goto retry_semop;
  289. } else
  290. if (res == -1) {
  291. return (CS_ERR_LIBRARY);
  292. }
  293. #endif
  294. return (CS_OK);
  295. }
  296. static inline cs_error_t
  297. ipc_sem_getvalue (
  298. struct control_buffer *control_buffer,
  299. enum ipc_semaphore_identifiers sem_id,
  300. int *sem_value)
  301. {
  302. #if _POSIX_THREAD_PROCESS_SHARED < 1
  303. int sem_value_hold;
  304. union semun semun;
  305. #else
  306. sem_t *sem = NULL;
  307. int res;
  308. #endif
  309. #if _POSIX_THREAD_PROCESS_SHARED > 0
  310. switch (sem_id) {
  311. case SEMAPHORE_REQUEST_OR_FLUSH_OR_EXIT:
  312. sem = &control_buffer->sem_request_or_flush_or_exit;
  313. break;
  314. case SEMAPHORE_RESPONSE:
  315. sem = &control_buffer->sem_request;
  316. break;
  317. case SEMAPHORE_DISPATCH:
  318. sem = &control_buffer->sem_response;
  319. break;
  320. case SEMAPHORE_REQUEST:
  321. sem = &control_buffer->sem_dispatch;
  322. break;
  323. }
  324. res = sem_getvalue (sem, sem_value);
  325. if (res == -1) {
  326. return (CS_ERR_LIBRARY);
  327. }
  328. #else
  329. retry_semctl:
  330. sem_value_hold = semctl (control_buffer->semid, sem_id, GETVAL, semun);
  331. if (sem_value_hold == -1 && errno == EINTR) {
  332. goto retry_semctl;
  333. } else
  334. if (sem_value_hold == -1) {
  335. return (CS_ERR_LIBRARY);
  336. }
  337. *sem_value = sem_value_hold;
  338. #endif
  339. return (CS_OK);
  340. }
  341. #endif /* COROIPC_IPC_H_DEFINED */