+
+int pthread_cond_wait(pthread_cond_t *p_cond, pthread_mutex_t *p_mutex) {
+ ModelExecution *execution = model->get_execution();
+ if ( !execution->getCondMap()->contains(p_cond) )
+ pthread_cond_init(p_cond, NULL);
+ if ( !execution->getMutexMap()->contains(p_mutex) )
+ pthread_mutex_init(p_mutex, NULL);
+
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+ cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
+
+ v->wait(*m);
+ return 0;
+}
+
+int pthread_cond_timedwait(pthread_cond_t *p_cond,
+ pthread_mutex_t *p_mutex, const struct timespec *abstime) {
+ ModelExecution *execution = model->get_execution();
+ if ( !execution->getCondMap()->contains(p_cond) )
+ pthread_cond_init(p_cond, NULL);
+ if ( !execution->getMutexMap()->contains(p_mutex) )
+ pthread_mutex_init(p_mutex, NULL);
+
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+ cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
+
+ uint64_t time = abstime->tv_sec * 1000000000 + abstime->tv_nsec;
+ ModelAction * timed_wait = new ModelAction(ATOMIC_TIMEDWAIT, std::memory_order_seq_cst, v, (uint64_t) m);
+ timed_wait->set_time(time);
+ if (model->switch_thread(timed_wait) == ETIMEDOUT) {
+ //model_print("thread %u wait timedout\n", thread_current_id());
+ return ETIMEDOUT;
+ }
+ m->lock();
+ return 0;
+}
+
+int pthread_cond_signal(pthread_cond_t *p_cond) {
+ // notify only one blocked thread
+ ModelExecution *execution = model->get_execution();
+ if ( !execution->getCondMap()->contains(p_cond) )
+ pthread_cond_init(p_cond, NULL);
+
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+
+ v->notify_one();
+ return 0;
+}
+
+int pthread_cond_broadcast(pthread_cond_t *p_cond) {
+ // notify all blocked threads
+ ModelExecution *execution = model->get_execution();
+ if ( !execution->getCondMap()->contains(p_cond) )
+ pthread_cond_init(p_cond, NULL);
+
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+
+ v->notify_all();
+ return 0;
+}
+
+int pthread_cond_destroy(pthread_cond_t *p_cond) {
+ ModelExecution *execution = model->get_execution();
+
+ if (execution->getCondMap()->contains(p_cond)) {
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+ delete v;
+ execution->getCondMap()->remove(p_cond);
+ }
+ return 0;
+}
+
+/* https://github.com/lattera/glibc/blob/master/nptl/pthread_getattr_np.c */
+int pthread_getattr_np(pthread_t t, pthread_attr_t *attr)
+{
+ ModelExecution *execution = model->get_execution();
+ Thread *th = execution->get_pthread(t);
+
+ struct pthread_attr *iattr = (struct pthread_attr *) attr;
+
+ /* The sizes are subject to alignment. */
+ if (th != NULL) {
+#if _STACK_GROWS_DOWN
+ ASSERT(false);
+#else
+ iattr->stackaddr = (char *) th->get_stack_addr();
+#endif
+
+ } else {
+ ASSERT(false);
+ }
+
+ return 0;
+}
+
+int pthread_setname_np(pthread_t t, const char *name)
+{
+ ModelExecution *execution = model->get_execution();
+ Thread *th = execution->get_pthread(t);
+
+ if (th != NULL)
+ return 0;
+
+ return 1;
+}