/* global "model" object */
#include "model.h"
#include "execution.h"
-extern "C" {
-int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
-}
-
-int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) {
- if (model) {
- uint64_t time = rqtp->tv_sec * 1000000000 + rqtp->tv_nsec;
- struct timespec currtime;
- clock_gettime(CLOCK_MONOTONIC, &currtime);
- uint64_t lcurrtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
- model->switch_to_master(new ModelAction(THREAD_SLEEP, std::memory_order_seq_cst, time, lcurrtime));
- if (rmtp != NULL) {
- clock_gettime(CLOCK_MONOTONIC, &currtime);
- uint64_t lendtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
- uint64_t elapsed = lendtime - lcurrtime;
- rmtp->tv_sec = elapsed / 1000000000;
- rmtp->tv_nsec = elapsed - rmtp->tv_sec * 1000000000;
- }
- }
- return 0;
-}
+#include <errno.h>
int pthread_create(pthread_t *t, const pthread_attr_t * attr,
- pthread_start_t start_routine, void * arg) {
+ pthread_start_t start_routine, void * arg) {
if (!model) {
snapshot_system_init(10000, 1024, 1024, 40000);
model = new ModelChecker();
return 0;
}
+/* Take care of both pthread_yield and c++ thread yield */
+int sched_yield() {
+ model->switch_to_master(new ModelAction(THREAD_YIELD, std::memory_order_seq_cst, thread_current(), VALUE_NONE));
+ return 0;
+}
+
void pthread_exit(void *value_ptr) {
Thread * th = thread_current();
th->set_pthread_return(value_ptr);
}
int pthread_mutex_timedlock (pthread_mutex_t *__restrict p_mutex,
- const struct timespec *__restrict abstime) {
+ const struct timespec *__restrict abstime) {
// timedlock just gives the option of giving up the lock, so return and let the scheduler decide which thread goes next
if (!model) {
if (m != NULL) {
m->lock();
- } else {
- return 1;
+ return 0;
}
- return 0;
+ return 1;
}
pthread_t pthread_self() {
+ if (!model) {
+ snapshot_system_init(10000, 1024, 1024, 40000);
+ model = new ModelChecker();
+ model->startChecker();
+ }
+
Thread* th = model->get_current_thread();
return (pthread_t)th->get_id();
}
}
int pthread_cond_timedwait(pthread_cond_t *p_cond,
- pthread_mutex_t *p_mutex, const struct timespec *abstime) {
+ pthread_mutex_t *p_mutex, const struct timespec *abstime) {
ModelExecution *execution = model->get_execution();
if ( !execution->getCondMap()->contains(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;
+}