libevfibers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
fiber.h
Go to the documentation of this file.
1 /********************************************************************
2 
3  Copyright 2013 Konstantin Olkhovskiy <lupus@oxnull.net>
4 
5  Licensed under the Apache License, Version 2.0 (the "License");
6  you may not use this file except in compliance with the License.
7  You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11  Unless required by applicable law or agreed to in writing, software
12  distributed under the License is distributed on an "AS IS" BASIS,
13  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  See the License for the specific language governing permissions and
15  limitations under the License.
16 
17  ********************************************************************/
18 
134 #ifndef _FBR_FIBER_H_
135 #define _FBR_FIBER_H_
136 
140 #include <unistd.h>
141 #include <stdarg.h>
142 #include <stddef.h>
143 #include <string.h>
144 #include <stdint.h>
145 #include <sys/types.h>
146 #include <sys/socket.h>
147 #include <sys/queue.h>
148 #include <assert.h>
149 #include <ev.h>
150 
151 #include <evfibers/config.h>
152 
156 #define FBR_CALL_STACK_SIZE 16
157 
160 #define FBR_STACK_SIZE (64 * 1024) /* 64 KB */
161 
166 #ifdef NDEBUG
167 #define fbr_assert(context, expr) ((void)(0))
168 #else
169 #define fbr_assert(context, expr) \
170  do { \
171  __typeof__(expr) ex = (expr); \
172  if (ex) \
173  (void)(0); \
174  else { \
175  fbr_dump_stack(context, fbr_log_e); \
176  __assert_fail(__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION); \
177  } \
178  } while (0)
179 #endif
180 
186 #define fbr_container_of(ptr, type, member) ({ \
187  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
188  (type *)( (char *)__mptr - offsetof(type,member) ); \
189  })
190 
191 struct fbr_context_private;
192 struct fbr_logger;
193 
194 struct fbr_id_s {
195  uint64_t g;
196  void *p;
197 } __attribute__((packed));
203 typedef struct fbr_id_s fbr_id_t;
204 
205 extern const fbr_id_t FBR_ID_NULL;
206 
207 static inline int fbr_id_eq(fbr_id_t a, fbr_id_t b)
208 {
209  return a.p == b.p && a.g == b.g;
210 }
211 
212 static inline int fbr_id_isnull(fbr_id_t a)
213 {
214  return fbr_id_eq(a, FBR_ID_NULL);
215 }
216 
225  FBR_SUCCESS = 0,
226  FBR_EINVAL,
227  FBR_ENOFIBER,
228  FBR_ESYSTEM,
229  FBR_EBUFFERMMAP,
230  FBR_ENOKEY,
231  FBR_EPROTOBUF,
232  FBR_EBUFFERNOSPACE,
233  FBR_EEIO,
234 };
235 
243 struct fbr_context {
244  struct fbr_context_private *__p;
247  struct fbr_logger *logger;
248 };
249 
253 #define FBR_P struct fbr_context *fctx
254 
258 #define FBR_PU __attribute__((unused)) FBR_P
259 
264 #define FBR_P_ FBR_P,
265 
269 #define FBR_PU_ __attribute__((unused)) FBR_P_
270 
274 #define FBR_A fctx
275 
280 #define FBR_A_ FBR_A,
281 
291 typedef void (*fbr_fiber_func_t)(FBR_P_ void *_arg);
292 
305 typedef void (*fbr_alloc_destructor_func_t)(FBR_P_ void *ptr, void *context);
306 
313  FBR_LOG_ERROR = 0,
314  FBR_LOG_WARNING,
315  FBR_LOG_NOTICE,
316  FBR_LOG_INFO,
317  FBR_LOG_DEBUG
318 };
319 
320 struct fbr_logger;
321 
334 typedef void (*fbr_log_func_t)(FBR_P_ struct fbr_logger *logger,
335  enum fbr_log_level level, const char *format, va_list ap);
336 
345 typedef void (*fbr_logutil_func_t)(FBR_P_ const char *format, ...);
346 
352 struct fbr_logger {
355  void *data;
356 };
357 
365 static inline int fbr_need_log(FBR_P_ enum fbr_log_level level)
366 {
367  return level <= fctx->logger->level;
368 }
369 
373 static inline void fbr_set_log_level(FBR_P_ enum fbr_log_level desired_level)
374 {
375  fctx->logger->level = desired_level;
376 }
377 
387 };
388 
389 struct fbr_ev_base;
390 
400 typedef void (*fbr_destructor_func_t)(FBR_P_ void *arg);
401 
423  void *arg;
424  TAILQ_ENTRY(fbr_destructor) entries; //Private
425  int active; //Private
426 };
427 
428 #define FBR_DESTRUCTOR_INITIALIZER { \
429  .func = NULL, \
430  .arg = NULL, \
431  .active = 0, \
432 };
433 
434 struct fbr_id_tailq;
435 
437  /* Private structure */
438  fbr_id_t id;
439  struct fbr_ev_base *ev;
440  TAILQ_ENTRY(fbr_id_tailq_i) entries;
441  struct fbr_destructor dtor;
442  struct fbr_id_tailq *head;
443 };
444 
445 TAILQ_HEAD(fbr_id_tailq, fbr_id_tailq_i);
446 
455 struct fbr_ev_base {
458  int arrived;
459  struct fbr_context *fctx; //Private
460  void *data; //Private
461  struct fbr_id_tailq_i item; //Private
462 };
463 
472 #define fbr_ev_upcast(ptr, type_no_struct) \
473  fbr_container_of(ptr, struct type_no_struct, ev_base)
474 
485  ev_watcher *w;
486  struct fbr_ev_base ev_base;
487 };
488 
496 struct fbr_ev_mutex {
497  struct fbr_mutex *mutex;
498  struct fbr_ev_base ev_base;
499 };
500 
509  struct fbr_cond_var *cond;
511  struct fbr_mutex *mutex;
512  struct fbr_ev_base ev_base;
513 };
514 
522 struct fbr_mutex {
523  fbr_id_t locked_by;
524  struct fbr_id_tailq pending;
525  TAILQ_ENTRY(fbr_mutex) entries;
526 };
527 
535 struct fbr_cond_var {
536  struct fbr_mutex *mutex;
537  struct fbr_id_tailq waiting;
538 };
539 
549 struct fbr_vrb {
550  void *mem_ptr;
551  size_t mem_ptr_size;
552  void *lower_ptr;
553  void *upper_ptr;
554  size_t ptr_size;
555  void *data_ptr;
556  void *space_ptr;
557 };
558 
569 struct fbr_buffer {
570  struct fbr_vrb vrb;
571  size_t prepared_bytes;
572  size_t waiting_bytes;
573  struct fbr_cond_var committed_cond;
574  struct fbr_mutex write_mutex;
575  struct fbr_cond_var bytes_freed_cond;
576  struct fbr_mutex read_mutex;
577 };
578 
587 typedef unsigned int fbr_key_t;
588 
589 
593 #define FBR_MAX_KEY 64
594 
595 
605 void fbr_destructor_add(FBR_P_ struct fbr_destructor *dtor);
606 
616 void fbr_destructor_remove(FBR_P_ struct fbr_destructor *dtor,
617  int call);
618 
628 static inline void fbr_destructor_init(struct fbr_destructor *dtor)
629 {
630  memset(dtor, 0x00, sizeof(*dtor));
631 }
632 
641 void fbr_ev_watcher_init(FBR_P_ struct fbr_ev_watcher *ev, ev_watcher *w);
642 
651 void fbr_ev_mutex_init(FBR_P_ struct fbr_ev_mutex *ev,
652  struct fbr_mutex *mutex);
653 
662 void fbr_ev_cond_var_init(FBR_P_ struct fbr_ev_cond_var *ev,
663  struct fbr_cond_var *cond, struct fbr_mutex *mutex);
664 
674 int fbr_ev_wait_one(FBR_P_ struct fbr_ev_base *one);
675 
687 int fbr_ev_wait(FBR_P_ struct fbr_ev_base *events[]);
688 
700 int fbr_ev_wait_to(FBR_P_ struct fbr_ev_base *events[], ev_tstamp timeout);
701 
711 int fbr_transfer(FBR_P_ fbr_id_t to);
712 
723 void fbr_init(struct fbr_context *fctx, struct ev_loop *loop);
724 
733 void fbr_destroy(FBR_P);
734 
745 void fbr_enable_backtraces(FBR_P, int enabled);
746 
753 const char *fbr_strerror(FBR_P_ enum fbr_error_code code);
754 
766 void fbr_log_e(FBR_P_ const char *format, ...)
767  __attribute__ ((format (printf, 2, 3)));
768 
780 void fbr_log_w(FBR_P_ const char *format, ...)
781  __attribute__ ((format (printf, 2, 3)));
782 
794 void fbr_log_n(FBR_P_ const char *format, ...)
795  __attribute__ ((format (printf, 2, 3)));
796 
808 void fbr_log_i(FBR_P_ const char *format, ...)
809  __attribute__ ((format (printf, 2, 3)));
810 
822 void fbr_log_d(FBR_P_ const char *format, ...)
823  __attribute__ ((format (printf, 2, 3)));
824 
828 #define FBR_MAX_FIBER_NAME 64
829 
856 fbr_id_t fbr_create(FBR_P_ const char *name, fbr_fiber_func_t func, void *arg,
857  size_t stack_size);
858 
872 const char *fbr_get_name(FBR_P_ fbr_id_t id);
873 
885 int fbr_set_name(FBR_P_ fbr_id_t id, const char *name);
886 
903 int fbr_disown(FBR_P_ fbr_id_t parent);
904 
914 fbr_id_t fbr_parent(FBR_P);
915 
931 int fbr_reclaim(FBR_P_ fbr_id_t fiber);
932 
933 int fbr_set_reclaim(FBR_P_ fbr_id_t fiber);
934 int fbr_set_noreclaim(FBR_P_ fbr_id_t fiber);
935 int fbr_want_reclaim(FBR_P_ fbr_id_t fiber);
936 
942 int fbr_is_reclaimed(FBR_P_ fbr_id_t fiber);
943 
948 fbr_id_t fbr_self(FBR_P);
949 
955 int fbr_key_create(FBR_P_ fbr_key_t *key);
956 
961 int fbr_key_delete(FBR_P_ fbr_key_t key);
962 
967 int fbr_key_set(FBR_P_ fbr_id_t id, fbr_key_t key, void *value);
968 
973 void *fbr_key_get(FBR_P_ fbr_id_t id, fbr_key_t key);
974 
986 void fbr_yield(FBR_P);
987 
997 void fbr_cooperate(FBR_P);
998 
1011 void *fbr_alloc(FBR_P_ size_t size);
1012 
1030  void *context);
1031 
1042 void *fbr_calloc(FBR_P_ unsigned int nmemb, size_t size);
1043 
1053 void fbr_free(FBR_P_ void *ptr);
1054 
1064 void fbr_free_nd(FBR_P_ void *ptr);
1065 
1075 int fbr_fd_nonblock(FBR_P_ int fd);
1076 
1092 int fbr_connect(FBR_P_ int sockfd, const struct sockaddr *addr,
1093  socklen_t addrlen);
1094 
1113 ssize_t fbr_read(FBR_P_ int fd, void *buf, size_t count);
1114 
1135 ssize_t fbr_read_all(FBR_P_ int fd, void *buf, size_t count);
1136 
1154 ssize_t fbr_readline(FBR_P_ int fd, void *buffer, size_t n);
1155 
1172 ssize_t fbr_write(FBR_P_ int fd, const void *buf, size_t count);
1173 
1192 ssize_t fbr_write_all(FBR_P_ int fd, const void *buf, size_t count);
1193 
1211 ssize_t fbr_recvfrom(FBR_P_ int sockfd, void *buf, size_t len, int flags,
1212  struct sockaddr *src_addr, socklen_t *addrlen);
1213 
1226 ssize_t fbr_recv(FBR_P_ int sockfd, void *buf, size_t len, int flags);
1227 
1245 ssize_t fbr_sendto(FBR_P_ int sockfd, const void *buf, size_t len, int flags, const
1246  struct sockaddr *dest_addr, socklen_t addrlen);
1247 
1259 ssize_t fbr_send(FBR_P_ int sockfd, const void *buf, size_t len, int flags);
1260 
1275 int fbr_accept(FBR_P_ int sockfd, struct sockaddr *addr, socklen_t *addrlen);
1276 
1285 ev_tstamp fbr_sleep(FBR_P_ ev_tstamp seconds);
1286 
1292 void fbr_dump_stack(FBR_P_ fbr_logutil_func_t log);
1293 
1307 void fbr_mutex_init(FBR_P_ struct fbr_mutex *mutex);
1308 
1321 void fbr_mutex_lock(FBR_P_ struct fbr_mutex *mutex);
1322 
1336 int fbr_mutex_trylock(FBR_P_ struct fbr_mutex *mutex);
1337 
1350 void fbr_mutex_unlock(FBR_P_ struct fbr_mutex *mutex);
1351 
1363 void fbr_mutex_destroy(FBR_P_ struct fbr_mutex *mutex);
1364 
1377 void fbr_cond_init(FBR_P_ struct fbr_cond_var *cond);
1378 
1389 void fbr_cond_destroy(FBR_P_ struct fbr_cond_var *cond);
1390 
1406 int fbr_cond_wait(FBR_P_ struct fbr_cond_var *cond, struct fbr_mutex *mutex);
1407 
1419 void fbr_cond_broadcast(FBR_P_ struct fbr_cond_var *cond);
1420 
1432 void fbr_cond_signal(FBR_P_ struct fbr_cond_var *cond);
1433 
1451 int fbr_vrb_init(struct fbr_vrb *vrb, size_t size, const char *file_pattern);
1452 
1453 
1462 void fbr_vrb_destroy(struct fbr_vrb *vrb);
1463 
1471 static inline size_t fbr_vrb_data_len(struct fbr_vrb *vrb)
1472 {
1473  return vrb->space_ptr - vrb->data_ptr;
1474 }
1475 
1483 static inline size_t fbr_vrb_space_len(struct fbr_vrb *vrb)
1484 {
1485  return vrb->data_ptr + vrb->ptr_size - vrb->space_ptr;
1486 }
1487 
1495 static inline size_t fbr_vrb_capacity(struct fbr_vrb *vrb)
1496 {
1497  return vrb->ptr_size;
1498 }
1499 
1507 static inline void *fbr_vrb_space_ptr(struct fbr_vrb *vrb)
1508 {
1509  return vrb->space_ptr;
1510 }
1511 
1519 static inline void *fbr_vrb_data_ptr(struct fbr_vrb *vrb)
1520 {
1521  return vrb->data_ptr;
1522 }
1523 
1537 static inline int fbr_vrb_give(struct fbr_vrb *vrb, size_t size)
1538 {
1539  if (size > fbr_vrb_space_len(vrb))
1540  return -1;
1541  vrb->space_ptr += size;
1542  return 0;
1543 }
1544 
1558 static inline int fbr_vrb_take(struct fbr_vrb *vrb, size_t size)
1559 {
1560  if (size > fbr_vrb_data_len(vrb))
1561  return -1;
1562  vrb->data_ptr += size;
1563 
1564  if (vrb->data_ptr >= vrb->upper_ptr) {
1565  vrb->data_ptr -= vrb->ptr_size;
1566  vrb->space_ptr -= vrb->ptr_size;
1567  }
1568 
1569  return 0;
1570 }
1571 
1581 static inline void fbr_vrb_reset(struct fbr_vrb *vrb)
1582 {
1583  vrb->data_ptr = vrb->lower_ptr;
1584  vrb->space_ptr = vrb->lower_ptr;
1585 }
1586 
1587 /* Private function */
1588 int fbr_vrb_resize_do(struct fbr_vrb *vrb, size_t new_size,
1589  const char *file_pattern);
1590 
1605 static inline int fbr_vrb_resize(struct fbr_vrb *vrb, size_t new_size,
1606  const char *file_pattern)
1607 {
1608  struct fbr_vrb tmp;
1609  int rv;
1610  if (fbr_vrb_capacity(vrb) >= new_size)
1611  return 0;
1612  memcpy(&tmp, vrb, sizeof(tmp));
1613  rv = fbr_vrb_init(vrb, new_size, file_pattern);
1614  if (rv) {
1615  memcpy(vrb, &tmp, sizeof(tmp));
1616  return rv;
1617  }
1618  memcpy(fbr_vrb_space_ptr(vrb), fbr_vrb_data_ptr(&tmp),
1619  fbr_vrb_data_len(&tmp));
1620  fbr_vrb_give(vrb, fbr_vrb_data_len(&tmp));
1621  fbr_vrb_destroy(&tmp);
1622  return 0;
1623 }
1624 
1625 
1637 int fbr_buffer_init(FBR_P_ struct fbr_buffer *buffer, size_t size);
1638 
1647 static inline size_t fbr_buffer_bytes(FBR_PU_ struct fbr_buffer *buffer)
1648 {
1649  return fbr_vrb_data_len(&buffer->vrb);
1650 }
1651 
1660 static inline size_t fbr_buffer_free_bytes(FBR_PU_ struct fbr_buffer *buffer)
1661 {
1662  return fbr_vrb_space_len(&buffer->vrb);
1663 }
1664 
1675 static inline size_t fbr_buffer_size(FBR_PU_ struct fbr_buffer *buffer)
1676 {
1677  return fbr_vrb_capacity(&buffer->vrb);
1678 }
1679 
1699 static inline void *fbr_buffer_space_ptr(FBR_PU_ struct fbr_buffer *buffer)
1700 {
1701  return fbr_vrb_space_ptr(&buffer->vrb);
1702 }
1703 
1723 static inline void *fbr_buffer_data_ptr(FBR_PU_ struct fbr_buffer *buffer)
1724 {
1725  return fbr_vrb_data_ptr(&buffer->vrb);
1726 }
1727 
1742 static inline void fbr_buffer_reset(FBR_PU_ struct fbr_buffer *buffer)
1743 {
1744  fbr_vrb_reset(&buffer->vrb);
1745 }
1746 
1747 
1755 void fbr_buffer_destroy(FBR_P_ struct fbr_buffer *buffer);
1756 
1772 void *fbr_buffer_alloc_prepare(FBR_P_ struct fbr_buffer *buffer, size_t size);
1773 
1782 void fbr_buffer_alloc_commit(FBR_P_ struct fbr_buffer *buffer);
1783 
1793 void fbr_buffer_alloc_abort(FBR_P_ struct fbr_buffer *buffer);
1794 
1808 void *fbr_buffer_read_address(FBR_P_ struct fbr_buffer *buffer, size_t size);
1809 
1819 void fbr_buffer_read_advance(FBR_P_ struct fbr_buffer *buffer);
1820 
1830 void fbr_buffer_read_discard(FBR_P_ struct fbr_buffer *buffer);
1831 
1848 int fbr_buffer_resize(FBR_P_ struct fbr_buffer *buffer, size_t size);
1849 
1855 static inline struct fbr_cond_var *fbr_buffer_cond_read(FBR_PU_
1856  struct fbr_buffer *buffer)
1857 {
1858  return &buffer->committed_cond;
1859 }
1860 
1866 static inline struct fbr_cond_var *fbr_buffer_cond_write(FBR_PU_
1867  struct fbr_buffer *buffer)
1868 {
1869  return &buffer->bytes_freed_cond;
1870 }
1871 
1881 static inline int fbr_buffer_wait_read(FBR_P_ struct fbr_buffer *buffer,
1882  size_t size)
1883 {
1884  struct fbr_mutex mutex;
1885  int retval;
1886  fbr_mutex_init(FBR_A_ &mutex);
1887  fbr_mutex_lock(FBR_A_ &mutex);
1888  while (fbr_buffer_bytes(FBR_A_ buffer) < size) {
1889  retval = fbr_cond_wait(FBR_A_ &buffer->committed_cond, &mutex);
1890  assert(0 == retval);
1891  (void)retval;
1892  }
1893  fbr_mutex_unlock(FBR_A_ &mutex);
1894  fbr_mutex_destroy(FBR_A_ &mutex);
1895  return 1;
1896 }
1897 
1907 static inline int fbr_buffer_can_read(FBR_P_ struct fbr_buffer *buffer,
1908  size_t size)
1909 {
1910  return fbr_buffer_bytes(FBR_A_ buffer) >= size;
1911 }
1912 
1922 static inline int fbr_buffer_wait_write(FBR_P_ struct fbr_buffer *buffer,
1923  size_t size)
1924 {
1925  struct fbr_mutex mutex;
1926  int retval;
1927  fbr_mutex_init(FBR_A_ &mutex);
1928  fbr_mutex_lock(FBR_A_ &mutex);
1929  while (fbr_buffer_free_bytes(FBR_A_ buffer) < size) {
1930  retval = fbr_cond_wait(FBR_A_ &buffer->bytes_freed_cond,
1931  &mutex);
1932  assert(0 == retval);
1933  (void)retval;
1934  }
1935  fbr_mutex_unlock(FBR_A_ &mutex);
1936  fbr_mutex_destroy(FBR_A_ &mutex);
1937  return 1;
1938 }
1939 
1949 static inline int fbr_buffer_can_write(FBR_P_ struct fbr_buffer *buffer,
1950  size_t size)
1951 {
1952  return fbr_buffer_free_bytes(FBR_A_ buffer) >= size;
1953 }
1954 
1963 void *fbr_get_user_data(FBR_P_ fbr_id_t id);
1964 
1974 int fbr_set_user_data(FBR_P_ fbr_id_t id, void *data);
1975 
1976 pid_t fbr_popen3(FBR_P_ const char *filename, char *const argv[],
1977  char *const envp[], const char *working_dir,
1978  int *stdin_w_ptr, int *stdout_r_ptr, int *stderr_r_ptr);
1979 
1980 static inline pid_t fbr_popen2(FBR_P_ const char *filename, char *const argv[],
1981  char *const envp[], const char *working_dir, int *stdin_w_ptr,
1982  int *stdout_r_ptr)
1983 {
1984  return fbr_popen3(FBR_A_ filename, argv, envp, working_dir, stdin_w_ptr,
1985  stdout_r_ptr, NULL);
1986 }
1987 
1988 static inline pid_t fbr_popen0(FBR_P_ const char *filename, char *const argv[],
1989  char *const envp[], const char *working_dir)
1990 {
1991  return fbr_popen3(FBR_A_ filename, argv, envp, working_dir, NULL, NULL,
1992  NULL);
1993 }
1994 
1995 int fbr_waitpid(FBR_P_ pid_t pid);
1996 
1997 int fbr_system(FBR_P_ const char *filename, char *const argv[],
1998  char *const envp[], const char *working_dir);
1999 
2000 #endif