ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered) { int retval; begin_read(ht1); begin_read(ht2); retval = zend_hash_compare(TS_HASH(ht1), TS_HASH(ht2), compar, ordered); end_read(ht2); end_read(ht1); return retval; }
int list_exists(struct linked_list_head *list, int val) { struct linked_list *p; begin_read(list->sync); p=list->head; while (p) { if (p->nb==val) { end_read(list->sync); return 1; } p=p->next; } end_read(list->sync); return 0; }
int exists(struct linked_list_head *list, int val) { struct linked_list *p; begin_read(&list->sync); sleep(rand()%3 + 1); p = list->head; while(p != NULL) { if (p->nb == val) { end_read(&list->sync); return 1; } p = p->next; } end_read(&list->sync); return 0; }
ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam) { begin_read(source); begin_write(target); zend_hash_merge_ex(TS_HASH(target), TS_HASH(source), pCopyConstructor, pMergeSource, pParam); end_write(target); end_read(source); }
ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, int overwrite) { begin_read(source); begin_write(target); zend_hash_merge(TS_HASH(target), TS_HASH(source), pCopyConstructor, overwrite); end_write(target); end_read(source); }
/** * Add task. * * Basically: * 1. Make sure we're not being destroyed, and prevent destruction until we're done (dest_lock) * 2. Lock the task queue (unconditionally - no upper limit on number of tasks) * 3. Add a task * 4. Release the task queue lock and signal that the queue isn't empty (which one first?) * 5. Unlock the destruction lock (now we can kill the thread pool) */ int tpInsertTask(ThreadPool* tp, void (*func)(void *), void* param) { start_read(tp); // Read the state, and generally prevent it's change if (tp->state != ALIVE) { // If the thread pool is dying, end_read(tp); // release the state for reading (no more writing will be done) return -1; // and return indication of destruction. } // Try creating the task now, before locking the queue but after reading, because this // takes a long time so we don't want to prevent tasks from running. We're currently still // "reading" the thread pool state, but that's OK because a. it's a CREW lock so the threads // can read and see that the thread pool is a live and b. if a writer wants to write to the // state it's because the writer wants to destroy the thread pool - we want to prevent that // anyway at this point. Task* t = (Task*)malloc(sizeof(Task)); if (!t) { end_read(tp); return -1; } t->func = func; t->param = param; // Editing the task queue now. // There's no danger of deadlock with thread acquiring this lock: If a thread isn't waiting // for a signal then all it does is read the state (we can allow that here even if we're // waiting for the task_lock) or do it's thing (dequeue or exit). Either way, it'll let go // of the lock eventually. We don't need to give the "add" function priority because the // worst case scenario is that it'll take some time to enqueue the task... But that's only // if the threads are busy, so the task won't get done anyway. pthread_mutex_lock(&tp->task_lock); PRINT("Adding a task, lock is locked\n"); osEnqueue(tp->tasks,(void*)t); // Signal before releasing the lock - make a thread wait for the lock. pthread_cond_signal(&tp->queue_not_empty_or_dying); PRINT("Task added, signal given, lock is locked\n"); pthread_mutex_unlock(&tp->task_lock); PRINT("Task added, signal given, lock is unlocked\n"); // Allow destruction of the thread pool (allow writing to pool->state) end_read(tp); return 0; }
ZEND_API int zend_ts_hash_exists(TsHashTable *ht, zend_string *key) { int retval; begin_read(ht); retval = zend_hash_exists(TS_HASH(ht), key); end_read(ht); return retval; }
ZEND_API zval *zend_ts_hash_index_find(TsHashTable *ht, zend_ulong h) { zval *retval; begin_read(ht); retval = zend_hash_index_find(TS_HASH(ht), h); end_read(ht); return retval; }
ZEND_API zval *zend_ts_hash_find(TsHashTable *ht, zend_string *key) { zval *retval; begin_read(ht); retval = zend_hash_find(TS_HASH(ht), key); end_read(ht); return retval; }
ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, zend_ulong h) { int retval; begin_read(ht); retval = zend_hash_index_exists(TS_HASH(ht), h); end_read(ht); return retval; }
ZEND_API int zend_ts_hash_num_elements(TsHashTable *ht) { int retval; begin_read(ht); retval = zend_hash_num_elements(TS_HASH(ht)); end_read(ht); return retval; }
ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, size_t len) { zval *retval; begin_read(ht); retval = zend_hash_str_find(TS_HASH(ht), key, len); end_read(ht); return retval; }
ZEND_API zval *zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag) { zval *retval; begin_read(ht); retval = zend_hash_minmax(TS_HASH(ht), compar, flag); end_read(ht); return retval; }
// Releases the reader_writer_lock void reader_writer_lock::unlock() { if( my_current_writer!=tbb_thread::id() ) { // A writer owns the lock __TBB_ASSERT(is_current_writer(), "caller of reader_writer_lock::unlock() does not own the lock."); __TBB_ASSERT(writer_head, NULL); __TBB_ASSERT(writer_head->status==active, NULL); scoped_lock *a_writer_lock = writer_head; end_write(a_writer_lock); __TBB_ASSERT(a_writer_lock != writer_head, "Internal error: About to turn writer_head into dangling reference."); delete a_writer_lock; } else { end_read(); } }
/* Loop reading + processing Ensemble upcalls. */ static void hot_mainloop(void *arg) { hot_contextID_t id; hot_cbType_t cb; while (1) { begin_read() ; { read_contextID(&id); trace("CALLBACK: group ID: %d", id); read_cbType(&cb); trace("CALLBACK: callback type: %d", cb); if (cb > CB_EXIT) hot_sys_Panic("bad callback type (%d)", cb); (*(callback[cb]))(id, &cb); } end_read () ; } }
void *lecteur(void *args) { donnees_thread_t *d = args; int i, valeur; srandom((int) pthread_self()); for (i=0; i < d->iterations; i++) { dodo(2); begin_read(d->lecteur_redacteur); printf("Thread %x : début lecture\n", (int) pthread_self()); valeur = d->donnee; dodo(1); printf("Thread %x : ", (int) pthread_self()); if (valeur != d->donnee) printf("LECTURE INCOHERENTE !!!\n"); else printf("lecture cohérente\n"); end_read(d->lecteur_redacteur); } pthread_exit(0); }
/** * Reads and returns the current state of the thread pool. * * Uses the reader functions above (implemented bellow). */ State read_state(ThreadPool* tp) { start_read(tp); State state = tp->state; end_read(tp); return state; }
ZEND_API void zend_ts_hash_copy_to_hash(HashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor) { begin_read(source); zend_hash_copy(target, TS_HASH(source), pCopyConstructor); end_read(source); }