Commits

Paweł Wieczorek  committed e582469

* dodano niedzialajace przelaczanie watkow

  • Participants
  • Parent commits 768d38c

Comments (0)

Files changed (8)

File examples/ex01.c

 {
     pwuthread_t t;
     pwuthread_create(&t, NULL, tmain, NULL);
-    pwuthread_join(t, NULL);
-    pwuthread_detach(t);
+    while (1);
     return 0;
 }

File include/pwuthread/private.h

     pwuthread_main_f *main;
     void *stack_addr;
     size_t stack_len;
+    int saved_error;
+    int flags;
 };
 
 void pwuthread_log(const char *fmt, ...);

File include/pwuthread/sched.h

 int pwuthread_sched_install(void);
 void pwuthread_sched_clocktick(void *u);
 pwuthread_t pwuthread_sched_next();
+void pwuthread_sched_switch(pwuthread_t t);
 
+void pwuthread_sched_enable();
+void pwuthread_sched_disable();
 #endif
     pwuthread_thread0 = PWUTHREAD_MALLOC(struct pwuthread);
     pwuthread_thread0->main = 0;
     pwuthread_thread0->main_arg = 0;
+    pwuthread_thread0->next = pwuthread_thread0;
+    pwuthread_thread0->prev = pwuthread_thread0;
+    pwuthread_thread0->flags = 1;
     pwuthread_current = pwuthread_thread0;
     pwuthread_ctx_init();
     pwuthread_sched_install();
     return n;
 }
 
+void
+pwuthread_sched_switch(pwuthread_t t)
+{
+    pwuthread_t old = pwuthread_current;
+    if (old == t) return;
+    if (!t->flags) return;
+    pwuthread_current = t;
+    pwuthread_log("switch %p -> %p", old, t);
+    old->saved_error = errno;
+    if (pwuthread_ctx_switch(t->context, old->context)) {
+        pwuthread_log("return %p <- ?%p", old, t); 
+        errno = old->saved_error;
+        pwuthread_current = old;
+    }
+}

File lib/thread.c

     pwuthread_init();
     thr = PWUTHREAD_MALLOC(struct pwuthread);
     thr->stack_len = 2*1024*1024;
+    thr->main = func;
+    thr->main_arg = arg;
+    thr->flags = 0;
     if (PWUTHREAD_ICALL(pwuthread_stack_alloc(&thr->stack_addr, thr->stack_len))) {
         return err;
     }
+    pwuthread_ctx_create(thr, thr->main, thr->stack_addr, thr->stack_len);
+    pwuthread_log("new uthread %p entry=%p arg=%p ctx=%p stack=%p+%x",
+        thr, thr->main, thr->main_arg, thr->context, thr->stack_addr,
+        thr->stack_len);
+    *t = thr;
     return 0;
 }
 

File support/unix_ctx_setjmp.c

 static void shortjump_handler(int n);
 static volatile int shortjump_raised;
 static sigset_t shortjump_waitmask;
+static pwuthread_t shortjump_thread;
 
 int
 pwuthread_ctx_init(void)
     shortjump_sa.sa_flags = SA_ONSTACK;
 
     sigfillset(&shortjump_waitmask);
-    sigdelset(&shortjump_waitmask, SIGUSR2);
-
+    sigdelset(&shortjump_waitmask, SIGUSR2);    
+    sigdelset(&shortjump_waitmask, SIGINT);
+    sigdelset(&shortjump_waitmask, SIGTSTP);
+    sigdelset(&shortjump_waitmask, SIGSEGV);
+    sigdelset(&shortjump_waitmask, SIGBUS);
+    sigdelset(&shortjump_waitmask, SIGILL);
+    sigdelset(&shortjump_waitmask, SIGFPE);
     pwuthread_current->context = PWUTHREAD_MALLOC(struct pwuthread_ctx);
     return 0;
 }
     stack_t oldstack;
     stack_t curstack;
     struct sigaction oldsa;
+    sigset_t oldmask;
 
+    pwuthread_log("new ctx");
     curstack.ss_sp = sa;
     curstack.ss_size = sl;
     curstack.ss_flags = 0;
 
+    if (sigprocmask(SIG_SETMASK, &shortjump_waitmask, &oldmask) == -1) {
+        pwuthread_perror("setting new sigmask");
+        return errno;
+    }
+
     if (sigaltstack(&curstack, &oldstack) == -1) {
-        int e = errno;
         pwuthread_perror("setting new sigaltstack");
-        return e;
+        return errno;
     }
 
     if (sigaction(SIGUSR2, &shortjump_sa, &oldsa) == -1) {
     }
 
     t->context = PWUTHREAD_MALLOC(struct pwuthread_ctx);
+    t->prev = pwuthread_current;
+    t->next = pwuthread_current->next;
+    pwuthread_current->next = t;
+    t->next->prev = t;
+    pwuthread_log("NEW %p -> %p", pwuthread_current, pwuthread_current->next);
+    pwuthread_log("NEW %p", &t);
     shortjump_raised = 0;
+    shortjump_thread = t;
     kill(getpid(), SIGUSR2);
 
     while (!shortjump_raised) {
         return errno;
     }
 
+    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
+        pwuthread_perror("setting old sigmask");
+        return errno;
+    }
+    pwuthread_log("uthread %p can work", t);
+    t->flags = 0;
+    longjmp(t->context->jb, 1);
     return 0;
 }
 
     if (setjmp(ctx0->jb) == 0) {
         longjmp(ctx1->jb, 1);
     } 
-    return 0;
+    return 1;
 }
 
 int
 pwuthread_ctx_detach(pwuthread_ctx_t ctx)
 {
-    return ENOTSUP;
+    free(ctx);
+    return 0;
 }
 
 void
 pwuthread_unix_sched_clocktick(void *u)
 {
-    
+    pwuthread_t next = pwuthread_sched_next();
+    pwuthread_sched_switch(next);
 }
 
 void
 shortjump_handler(int s)
 {
+    pwuthread_t thread = shortjump_thread;
+    pwuthread_log("trampoline called %p %p", thread, &thread);
+    if (setjmp(thread->context->jb)) {
+        pwuthread_log("continuation called");
+        thread->main_ret = thread->main(thread->main_arg);
+        while(1);
+    }
+    shortjump_thread = 0;
     shortjump_raised = 1;
 }
 

File support/unix_stack.c

 int
 pwuthread_stack_alloc(void **addr, size_t len)
 {
-    *addr = mmap(NULL, len, MAP_ANON, PROT_READ|PROT_WRITE, -1, 0);
+    enum {
+        prot = PROT_READ|PROT_WRITE,
+        flags = MAP_ANON|MAP_PRIVATE
+    };
+    *addr = mmap(NULL, len, prot, flags, -1, 0);
     if (*addr == MAP_FAILED) {
+        pwuthread_perror("maping stack");
         return errno;
     }
     return 0;
 pwuthread_stack_free(void *addr, size_t len)
 {
     if (munmap(addr, len) == -1) {
+        pwuthread_perror("unmaping stack");
         return errno;
     }
     return 0;