PJ_DEF(void) pj_caching_pool_init( pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity) { int i; pj_pool_t *pool; PJ_CHECK_STACK(); pj_bzero(cp, sizeof(*cp)); cp->max_capacity = max_capacity; pj_list_init(&cp->used_list); for (i=0; i<PJ_CACHING_POOL_ARRAY_SIZE; ++i) pj_list_init(&cp->free_list[i]); if (policy == NULL) { policy = &pj_pool_factory_default_policy; } pj_memcpy(&cp->factory.policy, policy, sizeof(pj_pool_factory_policy)); cp->factory.create_pool = &cpool_create_pool; cp->factory.release_pool = &cpool_release_pool; cp->factory.dump_status = &cpool_dump_status; cp->factory.on_block_alloc = &cpool_on_block_alloc; cp->factory.on_block_free = &cpool_on_block_free; pool = pj_pool_create_on_buf("cachingpool", cp->pool_buf, sizeof(cp->pool_buf)); pj_lock_create_simple_mutex(pool, "cachingpool", &cp->lock); }
PJ_DEF(pj_status_t) pj_ioqueue_register_sock2(pj_pool_t *pool, pj_ioqueue_t *ioqueue, pj_sock_t sock, pj_grp_lock_t *grp_lock, void *user_data, const pj_ioqueue_callback *cb, pj_ioqueue_key_t **p_key) { PjUwpSocketCallback uwp_cb = { &on_read, &on_write, &on_accept, &on_connect }; pj_ioqueue_key_t *key; pj_status_t rc; pj_lock_acquire(ioqueue->lock); key = PJ_POOL_ZALLOC_T(pool, pj_ioqueue_key_t); rc = ioqueue_init_key(pool, ioqueue, key, sock, grp_lock, user_data, cb); if (rc != PJ_SUCCESS) { key = NULL; goto on_return; } /* Create ioqueue key lock, if not yet */ if (!key->lock) { rc = pj_lock_create_simple_mutex(pool, NULL, &key->lock); if (rc != PJ_SUCCESS) { key = NULL; goto on_return; } } PjUwpSocket *s = (PjUwpSocket*)sock; s->SetNonBlocking(&uwp_cb, key); on_return: if (rc != PJ_SUCCESS) { if (key && key->grp_lock) pj_grp_lock_dec_ref_dbg(key->grp_lock, "ioqueue", 0); } *p_key = key; pj_lock_release(ioqueue->lock); return rc; }
/* * pj_ioqueue_create() * * Create select ioqueue. */ PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, pj_size_t max_fd, pj_ioqueue_t **p_ioqueue) { pj_ioqueue_t *ioqueue; pj_status_t rc; pj_lock_t *lock; int i; /* Check that arguments are valid. */ PJ_ASSERT_RETURN(pool != NULL && p_ioqueue != NULL && max_fd > 0, PJ_EINVAL); /* Check that size of pj_ioqueue_op_key_t is sufficient */ PJ_ASSERT_RETURN(sizeof(pj_ioqueue_op_key_t)-sizeof(void*) >= sizeof(union operation_key), PJ_EBUG); ioqueue = pj_pool_alloc(pool, sizeof(pj_ioqueue_t)); ioqueue_init(ioqueue); ioqueue->max = max_fd; ioqueue->count = 0; pj_list_init(&ioqueue->active_list); #if PJ_IOQUEUE_HAS_SAFE_UNREG /* When safe unregistration is used (the default), we pre-create * all keys and put them in the free list. */ /* Mutex to protect key's reference counter * We don't want to use key's mutex or ioqueue's mutex because * that would create deadlock situation in some cases. */ rc = pj_mutex_create_simple(pool, NULL, &ioqueue->ref_cnt_mutex); if (rc != PJ_SUCCESS) return rc; /* Init key list */ pj_list_init(&ioqueue->free_list); pj_list_init(&ioqueue->closing_list); /* Pre-create all keys according to max_fd */ for ( i=0; i<max_fd; ++i) { pj_ioqueue_key_t *key; key = PJ_POOL_ALLOC_T(pool, pj_ioqueue_key_t); key->ref_count = 0; rc = pj_lock_create_recursive_mutex(pool, NULL, &key->lock); if (rc != PJ_SUCCESS) { key = ioqueue->free_list.next; while (key != &ioqueue->free_list) { pj_lock_destroy(key->lock); key = key->next; } pj_mutex_destroy(ioqueue->ref_cnt_mutex); return rc; } pj_list_push_back(&ioqueue->free_list, key); } #endif rc = pj_lock_create_simple_mutex(pool, "ioq%p", &lock); if (rc != PJ_SUCCESS) return rc; rc = pj_ioqueue_set_lock(ioqueue, lock, PJ_TRUE); if (rc != PJ_SUCCESS) return rc; ioqueue->epfd = os_epoll_create(max_fd); if (ioqueue->epfd < 0) { ioqueue_destroy(ioqueue); return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); } /*ioqueue->events = pj_pool_calloc(pool, max_fd, sizeof(struct epoll_event)); PJ_ASSERT_RETURN(ioqueue->events != NULL, PJ_ENOMEM); ioqueue->queue = pj_pool_calloc(pool, max_fd, sizeof(struct queue)); PJ_ASSERT_RETURN(ioqueue->queue != NULL, PJ_ENOMEM); */ PJ_LOG(4, ("pjlib", "epoll I/O Queue created (%p)", ioqueue)); *p_ioqueue = ioqueue; return PJ_SUCCESS; }
/* * Create a master port. * */ PJ_DEF(pj_status_t) pjmedia_master_port_create( pj_pool_t *pool, pjmedia_port *u_port, pjmedia_port *d_port, unsigned options, pjmedia_master_port **p_m) { pjmedia_master_port *m; unsigned clock_rate; unsigned channel_count; unsigned samples_per_frame; unsigned bytes_per_frame; pj_status_t status; /* Sanity check */ PJ_ASSERT_RETURN(pool && u_port && d_port && p_m, PJ_EINVAL); /* Both ports MUST have equal clock rate */ PJ_ASSERT_RETURN(u_port->info.clock_rate == d_port->info.clock_rate, PJMEDIA_ENCCLOCKRATE); /* Both ports MUST have equal samples per frame */ PJ_ASSERT_RETURN(u_port->info.samples_per_frame== d_port->info.samples_per_frame, PJMEDIA_ENCSAMPLESPFRAME); /* Both ports MUST have equal channel count */ PJ_ASSERT_RETURN(u_port->info.channel_count == d_port->info.channel_count, PJMEDIA_ENCCHANNEL); /* Get clock_rate and samples_per_frame from one of the port. */ clock_rate = u_port->info.clock_rate; samples_per_frame = u_port->info.samples_per_frame; channel_count = u_port->info.channel_count; /* Get the bytes_per_frame value, to determine the size of the * buffer. We take the larger size of the two ports. */ bytes_per_frame = u_port->info.bytes_per_frame; if (d_port->info.bytes_per_frame > bytes_per_frame) bytes_per_frame = d_port->info.bytes_per_frame; /* Create the master port instance */ m = PJ_POOL_ZALLOC_T(pool, pjmedia_master_port); m->options = options; m->u_port = u_port; m->d_port = d_port; /* Create buffer */ m->buff_size = bytes_per_frame; m->buff = pj_pool_alloc(pool, m->buff_size); if (!m->buff) return PJ_ENOMEM; /* Create lock object */ status = pj_lock_create_simple_mutex(pool, "mport", &m->lock); if (status != PJ_SUCCESS) return status; /* Create media clock */ status = pjmedia_clock_create(pool, clock_rate, channel_count, samples_per_frame, options, &clock_callback, m, &m->clock); if (status != PJ_SUCCESS) { pj_lock_destroy(m->lock); return status; } /* Done */ *p_m = m; return PJ_SUCCESS; }
/* * pj_ioqueue_create() * * Create select ioqueue. */ PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, pj_size_t max_fd, pj_ioqueue_t **p_ioqueue) { pj_ioqueue_t *ioqueue; pj_lock_t *lock; unsigned i; pj_status_t rc; /* Check that arguments are valid. */ PJ_ASSERT_RETURN(pool != NULL && p_ioqueue != NULL && max_fd > 0 && max_fd <= PJ_IOQUEUE_MAX_HANDLES, PJ_EINVAL); /* Check that size of pj_ioqueue_op_key_t is sufficient */ PJ_ASSERT_RETURN(sizeof(pj_ioqueue_op_key_t)-sizeof(void*) >= sizeof(union operation_key), PJ_EBUG); /* Create and init common ioqueue stuffs */ ioqueue = PJ_POOL_ALLOC_T(pool, pj_ioqueue_t); ioqueue_init(ioqueue); ioqueue->max = max_fd; ioqueue->count = 0; PJ_FD_ZERO(&ioqueue->rfdset); PJ_FD_ZERO(&ioqueue->wfdset); #if PJ_HAS_TCP PJ_FD_ZERO(&ioqueue->xfdset); #endif pj_list_init(&ioqueue->active_list); rescan_fdset(ioqueue); #if PJ_IOQUEUE_HAS_SAFE_UNREG /* When safe unregistration is used (the default), we pre-create * all keys and put them in the free list. */ /* Mutex to protect key's reference counter * We don't want to use key's mutex or ioqueue's mutex because * that would create deadlock situation in some cases. */ rc = pj_mutex_create_simple(pool, NULL, &ioqueue->ref_cnt_mutex); if (rc != PJ_SUCCESS) return rc; /* Init key list */ pj_list_init(&ioqueue->free_list); pj_list_init(&ioqueue->closing_list); /* Pre-create all keys according to max_fd */ for (i=0; i<max_fd; ++i) { pj_ioqueue_key_t *key; key = PJ_POOL_ALLOC_T(pool, pj_ioqueue_key_t); key->ref_count = 0; rc = pj_mutex_create_recursive(pool, NULL, &key->mutex); if (rc != PJ_SUCCESS) { key = ioqueue->free_list.next; while (key != &ioqueue->free_list) { pj_mutex_destroy(key->mutex); key = key->next; } pj_mutex_destroy(ioqueue->ref_cnt_mutex); return rc; } pj_list_push_back(&ioqueue->free_list, key); } #endif /* Create and init ioqueue mutex */ rc = pj_lock_create_simple_mutex(pool, "ioq%p", &lock); if (rc != PJ_SUCCESS) return rc; rc = pj_ioqueue_set_lock(ioqueue, lock, PJ_TRUE); if (rc != PJ_SUCCESS) return rc; PJ_LOG(4, ("pjlib", "select() I/O Queue created (%p)", ioqueue)); *p_ioqueue = ioqueue; return PJ_SUCCESS; }
static pj_status_t ioqueue_init_key( pj_pool_t *pool, pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *key, pj_sock_t sock, pj_grp_lock_t *grp_lock, void *user_data, const pj_ioqueue_callback *cb) { pj_status_t rc; int optlen; PJ_UNUSED_ARG(pool); key->ioqueue = ioqueue; key->fd = sock; key->user_data = user_data; pj_list_init(&key->read_list); pj_list_init(&key->write_list); #if PJ_HAS_TCP pj_list_init(&key->accept_list); key->connecting = 0; #endif /* Save callback. */ pj_memcpy(&key->cb, cb, sizeof(pj_ioqueue_callback)); #if PJ_IOQUEUE_HAS_SAFE_UNREG /* Set initial reference count to 1 */ pj_assert(key->ref_count == 0); ++key->ref_count; key->closing = 0; #endif rc = pj_ioqueue_set_concurrency(key, ioqueue->default_concurrency); if (rc != PJ_SUCCESS) return rc; /* Get socket type. When socket type is datagram, some optimization * will be performed during send to allow parallel send operations. */ optlen = sizeof(key->fd_type); rc = pj_sock_getsockopt(sock, pj_SOL_SOCKET(), pj_SO_TYPE(), &key->fd_type, &optlen); if (rc != PJ_SUCCESS) key->fd_type = pj_SOCK_STREAM(); /* Create mutex for the key. */ #if !PJ_IOQUEUE_HAS_SAFE_UNREG rc = pj_lock_create_simple_mutex(poll, NULL, &key->lock); #endif if (rc != PJ_SUCCESS) return rc; /* Group lock */ key->grp_lock = grp_lock; if (key->grp_lock) { pj_grp_lock_add_ref_dbg(key->grp_lock, "ioqueue", 0); } return PJ_SUCCESS; }
// // Default constructor. // explicit Pj_Simple_Mutex_Lock(Pj_Pool *pool, const char *name = NULL) : Pj_Lock(NULL) { pj_lock_create_simple_mutex(pool->pool_(), name, &lock_); }