Commits

Paweł Wieczorek committed c6de7f5

* prace nad unix_ctx_setjmp

Comments (0)

Files changed (7)

     examples/ex02.c\
 
 SUPPORT_SRC=\
-    support/unix_ctx_ucontext.c\
+    support/unix_ctx_setjmp.c\
+    support/unix_sched.c\
 
 OBJS= ${SRCS:%.c=%.o}
 EXAMPLES= ${EXAMPLE_SRC:%.c=%}

include/pwuthread/private.h

 void pwuthread_log(const char *fmt, ...);
 int pwuthread_init(void);
 
+extern int pwuthread_sched_quantuum;
+
 #define PWUTHREAD_MALLOC(type) (type*)malloc(sizeof(type))
 #define PWUTHREAD_ICALL(c) ( (err = c) ) 
 #endif

include/pwuthread/sched.h

+#ifndef PWUTHREAD_SCHED_H
+#define PWUTHREAD_SCHED_H
+
+void pwuthread_sched_install(void);
+void *pwuthread_sched_clocktick(siginfo_t *si, void *u);
+
+#endif
 #include "pwuthread/private.h"
 
 static int initialized = 0;
-static int sched_type = PWUTHREAD_SCHED_PREEMPTIVE;
+int pwuthread_sched_type = PWUTHREAD_SCHED_PREEMPTIVE;
+int pwuthread_cancel_state = PWUTHREAD_CANCEL_ENABLE;
+int pwuthread_cancel_type = PWUTHREAD_CANCEL_DEFERED;
+int pwuthread_sched_quantuum = 50000;
 
 int
 pwuthread_init(void)
     switch (st) {
         case PWUTHREAD_SCHED_PREEMPTIVE:
         case PWUTHREAD_SCHED_COOPERATIVE:
-            if (ost) *ost = sched_type;
-            sched_type = st;
+            if (ost) *ost = pwuthread_sched_type;
+            pwuthread_sched_type = st;
             r = 0;
             break;
         default:
     return r;
 }
 
+int
+pwuthread_setcancelstate(int st, int *ost)
+{
+    int r;
+    if (initialized) return EBUSY;
+    switch (st) {
+        case PWUTHREAD_CANCEL_ENABLE:
+        case PWUTHREAD_CANCEL_DISABLE:
+            if (ost) *ost = pwuthread_cancel_state;
+            pwuthread_cancel_state = st;
+            r = 0;
+            break;
+        default:
+            r = EINVAL;
+            break;
+    }
+    return r;
+}
+
+int
+pwuthread_setcanceltype(int t, int *ot)
+{
+    int r;
+    if (initialized) return EBUSY;
+    switch (t) {
+        case PWUTHREAD_CANCEL_DEFERED:
+        case PWUTHREAD_CANCEL_ASYNCHRONOUS:
+            if (ot) *ot = pwuthread_cancel_type;
+            pwuthread_cancel_type = t;
+            r = 0;
+            break;
+        default:
+            r = EINVAL;
+            break;
+    }
+    return r;
+}
+
 pwuthread_create(pwuthread_t *t, pwuthread_attr_t *a,
     pwuthread_main_f *func, void *arg)
 {
+    pwuthread_t thr = PWUTHREAD_MALLOC(struct pwuthread);
     return ENOTSUP;
 }
 
 int
 pwuthread_join(pwuthread_t t, void **arg)
 {
+    if (arg) *arg = t->main_ret;
     return ENOTSUP;
 }
 

support/unix_ctx_setjmp.c

 #include "pwuthread/private.h"
 #include <setjmp.h>
+#include <signal.h>
+#include <unistd.h>
 
 struct pwuthread_ctx {
     jmp_buf jb;
     pwuthread_main_f *func;
 };
 
+static struct sigaction shortjump_sa;
+static void shortjump_handler(int n);
+static volatile int shortjump_raised;
+static sigset_t shortjump_waitmask;
+
+int
+pwuthread_ctx_init(void)
+{
+    sigfillset(&shortjump_sa.sa_mask);
+    shortjump_sa.sa_handler = shortjump_handler;
+    shortjump_sa.sa_flags = SA_ONSTACK;
+
+    sigfillset(&shortjump_waitmask);
+    sigdelset(&shortjump_waitmask, SIGUSR2);
+    return 0;
+}
+
 int
 pwuthread_ctx_create(pwuthread_t t, pwuthread_main_f *func,
     void *sa, size_t sl )
 {
-    return ENOTSUP;
+    stack_t oldstack;
+    stack_t curstack;
+    struct sigaction oldsa;
+
+    curstack.ss_sp = sa;
+    curstack.ss_size = sl;
+    curstack.ss_flags = 0;
+
+    if (sigaltstack(&curstack, &oldstack) == -1) {
+        return errno;
+    }
+
+    if (sigaction(SIGUSR2, &shortjump_sa, &oldsa) == -1) {
+        return errno;
+    }
+
+    shortjump_raised = 0;
+    kill(getpid(), SIGUSR2);
+
+    while (!shortjump_raised) {
+        if (sigsuspend(&shortjump_waitmask) != -1  && errno != EINTR) {
+            return errno;
+        } 
+    }
+
+    if (sigaction(SIGUSR2, &oldsa, NULL) == -1) {
+        return errno;
+    }
+
+    if (sigaltstack(&oldstack, &curstack)) {
+    }
+
+    return 0;
 }
 
 int
 pwuthread_ctx_switch(pwuthread_ctx_t ctx0, pwuthread_ctx_t ctx1)
 {
-    return ENOTSUP;
+    if (setjmp(ctx0->jb) == 0) {
+        longjmp(ctx1->jb, 1);
+    } 
+    return 0;
 }
 
 int
     return ENOTSUP;
 }
 
+void
+pwuthread_unix_sched_clocktick(void *u)
+{
+    
+}
+
+void
+shortjump_handler(int s)
+{
+    shortjump_raised = 1;
+}
+

support/unix_sched.c

+#include "pwuthread/private.h"
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+
+static void sched_clocktick(int sn, siginfo_t *si, void *u);
+
+void pwuthread_unix_sched_clocktick(void *u);
+
+int
+pwuthread_sched_install(void)
+{
+    struct sigaction sa;
+    struct timeval tv;
+    struct itimerval itv;
+
+    sa.sa_flags = SA_SIGINFO|SA_NODEFER;
+    sa.sa_sigaction = sched_clocktick;
+    sigfillset(&sa.sa_mask);
+    sigdelset(&sa.sa_mask, SIGINT);
+    sigdelset(&sa.sa_mask, SIGTSTP);
+    sigdelset(&sa.sa_mask, SIGFPE);
+
+    if (sigaction(SIGALRM, &sa, NULL) == -1) {
+        return errno;
+    }
+
+    tv.tv_sec = 0;
+    tv.tv_usec = pwuthread_sched_quantuum;
+    itv.it_value = tv;
+    itv.it_interval = tv;
+    if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
+        return errno;
+    }
+    return 0;
+}
+
+void
+sched_clocktick(int sn, siginfo_t *si, void *u)
+{
+    pwuthread_unix_sched_clocktick(u);
+}
+