Bläddra i källkod

system: add BThreadSignal and BLockReactor

ambrop7 13 år sedan
förälder
incheckning
86b3cbc925

+ 2 - 0
blog_channels.txt

@@ -140,3 +140,5 @@ ncd_log 4
 ncd_log_msg 4
 ncd_buffer 4
 ncd_getenv 4
+BThreadSignal 4
+BLockReactor 4

+ 4 - 0
generated/blog_channel_BLockReactor.h

@@ -0,0 +1,4 @@
+#ifdef BLOG_CURRENT_CHANNEL
+#undef BLOG_CURRENT_CHANNEL
+#endif
+#define BLOG_CURRENT_CHANNEL BLOG_CHANNEL_BLockReactor

+ 4 - 0
generated/blog_channel_BThreadSignal.h

@@ -0,0 +1,4 @@
+#ifdef BLOG_CURRENT_CHANNEL
+#undef BLOG_CURRENT_CHANNEL
+#endif
+#define BLOG_CURRENT_CHANNEL BLOG_CHANNEL_BThreadSignal

+ 3 - 1
generated/blog_channels_defines.h

@@ -140,4 +140,6 @@
 #define BLOG_CHANNEL_ncd_log_msg 139
 #define BLOG_CHANNEL_ncd_buffer 140
 #define BLOG_CHANNEL_ncd_getenv 141
-#define BLOG_NUM_CHANNELS 142
+#define BLOG_CHANNEL_BThreadSignal 142
+#define BLOG_CHANNEL_BLockReactor 143
+#define BLOG_NUM_CHANNELS 144

+ 2 - 0
generated/blog_channels_list.h

@@ -140,3 +140,5 @@
 {"ncd_log_msg", 4},
 {"ncd_buffer", 4},
 {"ncd_getenv", 4},
+{"BThreadSignal", 4},
+{"BLockReactor", 4},

+ 131 - 0
system/BLockReactor.c

@@ -0,0 +1,131 @@
+/**
+ * @file BLockReactor.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <misc/debug.h>
+#include <misc/offset.h>
+#include <base/BLog.h>
+
+#include "BLockReactor.h"
+
+#include <generated/blog_channel_BLockReactor.h>
+
+static void thread_signal_handler (BThreadSignal *thread_signal)
+{
+    BLockReactor *o = UPPER_OBJECT(thread_signal, BLockReactor, thread_signal);
+    DebugObject_Access(&o->d_obj);
+    
+    ASSERT_FORCE(sem_post(&o->sem1) == 0)
+    ASSERT_FORCE(sem_wait(&o->sem2) == 0)
+}
+
+int BLockReactor_Init (BLockReactor *o, BReactor *reactor)
+{
+    o->reactor = reactor;
+    
+    if (!BThreadSignal_Init(&o->thread_signal, reactor, thread_signal_handler)) {
+        BLog(BLOG_ERROR, "BThreadSignal_Init failed");
+        goto fail0;
+    }
+    
+    if (sem_init(&o->sem1, 0, 0) < 0) {
+        BLog(BLOG_ERROR, "sem_init failed");
+        goto fail1;
+    }
+    
+    if (sem_init(&o->sem2, 0, 0) < 0) {
+        BLog(BLOG_ERROR, "sem_init failed");
+        goto fail2;
+    }
+    
+#ifndef NDEBUG
+    o->locked = 0;
+#endif
+    
+    DebugObject_Init(&o->d_obj);
+    return 1;
+    
+fail2:
+    if (sem_close(&o->sem1) < 0) {
+        BLog(BLOG_ERROR, "sem_close failed");
+    }
+fail1:
+    BThreadSignal_Free(&o->thread_signal);
+fail0:
+    return 0;
+}
+
+void BLockReactor_Free (BLockReactor *o)
+{
+    DebugObject_Free(&o->d_obj);
+#ifndef NDEBUG
+    ASSERT(!o->locked)
+#endif
+    
+    if (sem_destroy(&o->sem2) < 0) {
+        BLog(BLOG_ERROR, "sem_close failed");
+    }
+    if (sem_destroy(&o->sem1) < 0) {
+        BLog(BLOG_ERROR, "sem_close failed");
+    }
+    BThreadSignal_Free(&o->thread_signal);
+}
+
+int BLockReactor_Thread_Lock (BLockReactor *o)
+{
+    DebugObject_Access(&o->d_obj);
+#ifndef NDEBUG
+    ASSERT(!o->locked)
+#endif
+    
+    if (!BThreadSignal_Thread_Signal(&o->thread_signal)) {
+        return 0;
+    }
+    
+    ASSERT_FORCE(sem_wait(&o->sem1) == 0)
+    
+#ifndef NDEBUG
+    o->locked = 1;
+#endif
+    
+    return 1;
+}
+
+void BLockReactor_Thread_Unlock (BLockReactor *o)
+{
+    DebugObject_Access(&o->d_obj);
+#ifndef NDEBUG
+    ASSERT(o->locked)
+#endif
+    
+#ifndef NDEBUG
+    o->locked = 0;
+#endif
+    
+    ASSERT_FORCE(sem_post(&o->sem2) == 0)
+}

+ 58 - 0
system/BLockReactor.h

@@ -0,0 +1,58 @@
+/**
+ * @file BLockReactor.h
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BADVPN_B_LOCK_REACTOR_H
+#define BADVPN_B_LOCK_REACTOR_H
+
+#include <semaphore.h>
+
+#include <misc/debug.h>
+#include <base/DebugObject.h>
+#include <system/BReactor.h>
+#include <system/BThreadSignal.h>
+
+typedef struct BLockReactor_s BLockReactor;
+
+struct BLockReactor_s {
+    BReactor *reactor;
+    BThreadSignal thread_signal;
+    sem_t sem1;
+    sem_t sem2;
+#ifndef NDEBUG
+    int locked;
+#endif
+    DebugObject d_obj;
+};
+
+int BLockReactor_Init (BLockReactor *o, BReactor *reactor) WARN_UNUSED;
+void BLockReactor_Free (BLockReactor *o);
+int BLockReactor_Thread_Lock (BLockReactor *o);
+void BLockReactor_Thread_Unlock (BLockReactor *o);
+
+#endif

+ 136 - 0
system/BThreadSignal.c

@@ -0,0 +1,136 @@
+/**
+ * @file BThreadSignal.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <misc/debug.h>
+#include <misc/nonblocking.h>
+#include <base/BLog.h>
+
+#include "BThreadSignal.h"
+
+#include <generated/blog_channel_BThreadSignal.h>
+
+static void bfd_handler (void *user, int events)
+{
+    BThreadSignal *o = user;
+    DebugObject_Access(&o->d_obj);
+    
+    char byte;
+    ssize_t res = read(o->pipe[0], &byte, sizeof(byte));
+    
+    if (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+        return;
+    }
+    
+    if (res < 0) {
+        BLog(BLOG_ERROR, "read failed");
+        return;
+    }
+    
+    if (res != sizeof(byte)) {
+        BLog(BLOG_ERROR, "bad read");
+        return;
+    }
+    
+    o->handler(o);
+}
+
+int BThreadSignal_Init (BThreadSignal *o, BReactor *reactor, BThreadSignal_handler handler)
+{
+    o->reactor = reactor;
+    o->handler = handler;
+    
+    if (pipe(o->pipe) < 0) {
+        BLog(BLOG_ERROR, "pipe failed");
+        goto fail0;
+    }
+    
+    if (!badvpn_set_nonblocking(o->pipe[0]) || !badvpn_set_nonblocking(o->pipe[1])) {
+        BLog(BLOG_ERROR, "badvpn_set_nonblocking failed");
+        goto fail1;
+    }
+    
+    BFileDescriptor_Init(&o->bfd, o->pipe[0], bfd_handler, o);
+    
+    if (!BReactor_AddFileDescriptor(o->reactor, &o->bfd)) {
+        BLog(BLOG_ERROR, "BReactor_AddFileDescriptor failed");
+        goto fail1;
+    }
+    
+    BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, BREACTOR_READ);
+    
+    DebugObject_Init(&o->d_obj);
+    return 1;
+    
+fail1:
+    if (close(o->pipe[1]) < 0) {
+        BLog(BLOG_ERROR, "close failed");
+    }
+    if (close(o->pipe[0]) < 0) {
+        BLog(BLOG_ERROR, "close failed");
+    }
+fail0:
+    return 0;
+}
+
+void BThreadSignal_Free (BThreadSignal *o)
+{
+    DebugObject_Free(&o->d_obj);
+    
+    BReactor_RemoveFileDescriptor(o->reactor, &o->bfd);
+    
+    if (close(o->pipe[1]) < 0) {
+        BLog(BLOG_ERROR, "close failed");
+    }
+    if (close(o->pipe[0]) < 0) {
+        BLog(BLOG_ERROR, "close failed");
+    }
+}
+
+int BThreadSignal_Thread_Signal (BThreadSignal *o)
+{
+    DebugObject_Access(&o->d_obj);
+    
+    char byte = 0;
+    ssize_t res = write(o->pipe[1], &byte, sizeof(byte));
+    
+    if (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+        return 0;
+    }
+    
+    if (res < 0) {
+        BLog(BLOG_ERROR, "write failed");
+    } else if (res != sizeof(byte)) {
+        BLog(BLOG_ERROR, "bad write");
+    }
+    
+    return 1;
+}

+ 53 - 0
system/BThreadSignal.h

@@ -0,0 +1,53 @@
+/**
+ * @file BThreadSignal.h
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BADVPN_B_THREAD_SIGNAL_H
+#define BADVPN_B_THREAD_SIGNAL_H
+
+#include <misc/debug.h>
+#include <base/DebugObject.h>
+#include <system/BReactor.h>
+
+typedef struct BThreadSignal_s BThreadSignal;
+
+typedef void (*BThreadSignal_handler) (BThreadSignal *thread_signal);
+
+struct BThreadSignal_s {
+    BReactor *reactor;
+    BThreadSignal_handler handler;
+    int pipe[2];
+    BFileDescriptor bfd;
+    DebugObject d_obj;
+};
+
+int BThreadSignal_Init (BThreadSignal *o, BReactor *reactor, BThreadSignal_handler handler) WARN_UNUSED;
+void BThreadSignal_Free (BThreadSignal *o);
+int BThreadSignal_Thread_Signal (BThreadSignal *o);
+
+#endif

+ 2 - 0
system/CMakeLists.txt

@@ -22,6 +22,8 @@ if (NOT EMSCRIPTEN)
             BDatagram_unix.c
             BProcess.c
             BInputProcess.c
+            BThreadSignal.c
+            BLockReactor.c
         )
     endif ()
 endif ()