From 4ef44158c06740e7158a1ef7c487aba05e8b9a4a Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Tue, 21 Jun 2022 00:28:35 +0300 Subject: [PATCH] Generic mutex (#77) --- .gitignore | 1 + ChangeLog | 5 +- Makefile.am | 7 ++- README.md | 8 ++- examples/Makefile.am | 8 +++ examples/generic_mutex.c | 76 +++++++++++++++++++++++++++ include/Makefile.am | 4 +- include/kernaux.h.in | 3 +- include/kernaux/alloc.h | 2 +- include/kernaux/{ => generic}/mutex.h | 11 ++-- include/kernaux/macro.h | 15 ++++-- src/{ => generic}/mutex.c | 6 +-- tests/test_alloc.c | 2 +- tests/test_memmap.c | 2 +- 14 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 examples/generic_mutex.c rename include/kernaux/{ => generic}/mutex.h (51%) rename src/{ => generic}/mutex.c (75%) diff --git a/.gitignore b/.gitignore index 7bd2910..7a3a7aa 100644 --- a/.gitignore +++ b/.gitignore @@ -110,6 +110,7 @@ /examples/cmdline /examples/fprintf /examples/fprintf_va +/examples/generic_mutex /examples/memmap /examples/ntoa /examples/panic diff --git a/ChangeLog b/ChangeLog index ce2d424..dddbe4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ 2022-06-20 Alex Kotov - * include/kernaux/alloc.h: Finished, made stable + * include/kernaux/alloc.h: Finished + * include/kernaux/generic/mutex.h: Mutex moved here + * include/kernaux/macro.h: Definitions "KERNAUX_ACCESS_*" made stable + * include/kernaux/macro.h: Macro "KERNAUX_PROTECTED_FIELD" added 2022-06-18 Alex Kotov diff --git a/Makefile.am b/Makefile.am index 2f74607..859cf7d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,12 +19,15 @@ endif libc/libc.la: $(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/libc libc.la -AM_CFLAGS += -DKERNAUX_PRIVATE_NO +AM_CFLAGS += -DKERNAUX_ACCESS_PRIVATE lib_LTLIBRARIES = libkernaux.la -libkernaux_la_SOURCES = src/libc.h src/assert.c src/mutex.c libkernaux_la_LIBADD = +libkernaux_la_SOURCES = \ + src/assert.c \ + src/libc.h \ + src/generic/mutex.c if ASM_I386 libkernaux_la_SOURCES += src/asm/i386.S diff --git a/README.md b/README.md index 807e2d0..140ca1b 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,12 @@ zero). Work-in-progress APIs can change at any time. * [Example: Assert](/examples/assert.c) * [Example: Panic](/examples/panic.c) * Stack trace *(planned)* - * [Mutex](/include/kernaux/mutex.h) (*non-breaking since* **?.?.?**) * [Input/output](/include/kernaux/io.h) (*work in progress*) * Architecture-specific code (*work in progress*) * [Declarations](/include/kernaux/arch/) * [Functions](/include/kernaux/asm/) +* Generic types + * [Mutex](/include/kernaux/generic/mutex.h) (*non-breaking since* **?.?.?**) * Device drivers (for debugging only) * [Serial console](/include/kernaux/console.h) (*work in progress*) * [Framebuffer](/include/kernaux/framebuffer.h) (*planned*) @@ -94,7 +95,10 @@ zero). Work-in-progress APIs can change at any time. Define the following C preprocessor macros before including `` and `` files. They have effect on your code, not the library code. -* `KERNAUX_DEBUG` - enable assertions +* `KERNAUX_DEBUG` - enable assertions. +* `KERNAUX_ACCESS_PRIVATE` - disable access modifier "private". Don't do this! +* `KERNAUX_ACCESS_PROTECTED` - disable access modifier "protected". Only do this + (with `#define`) in a file where you implement an inherited type. ### Global variables diff --git a/examples/Makefile.am b/examples/Makefile.am index faf4a34..79740d2 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -45,6 +45,14 @@ fprintf_va_SOURCES = main.c fprintf_va.c endif endif +################# +# generic_mutex # +################# + +TESTS += generic_mutex +generic_mutex_LDADD = $(top_builddir)/libkernaux.la +generic_mutex_SOURCES = main.c generic_mutex.c + ########## # memmap # ########## diff --git a/examples/generic_mutex.c b/examples/generic_mutex.c new file mode 100644 index 0000000..370bbbb --- /dev/null +++ b/examples/generic_mutex.c @@ -0,0 +1,76 @@ +//============ +// my_mutex.c +//============ + +// To not always use macro "KERNAUX_PROTECTED_FIELD" around the names of +// structure fields you may define "KERNAUX_ACCESS_PROTECTED" before including +// any other headers, but ONLY in the file where you implement a generic type. +// +#define KERNAUX_ACCESS_PROTECTED + +//============ +// my_mutex.h +//============ + +#include +#include + +typedef struct MyMutex { + struct KernAux_Mutex mutex; + pthread_mutex_t pthread_mutex; +} *MyMutex; + +struct MyMutex MyMytex_create(); + +//============ +// my_mutex.c +//============ + +#include +#include +#include + +static void MyMutex_lock (void *mutex); +static void MyMutex_unlock(void *mutex); + +struct MyMutex MyMutex_create() +{ + struct MyMutex my_mutex; + my_mutex.mutex.lock = MyMutex_lock; + my_mutex.mutex.unlock = MyMutex_unlock; + if (pthread_mutex_init(&my_mutex.pthread_mutex, NULL) != 0) abort(); + return my_mutex; +} + +void MyMutex_lock(void *const mutex) +{ + MyMutex my_mutex = mutex; + pthread_mutex_lock(&my_mutex->pthread_mutex); +} + +void MyMutex_unlock(void *const mutex) +{ + MyMutex my_mutex = mutex; + pthread_mutex_unlock(&my_mutex->pthread_mutex); +} + +//======== +// main.c +//======== + +static int shared_counter = 0; + +void example_main() +{ + // Create mutex + struct MyMutex my_mutex = MyMutex_create(); + + // Lock mutex + KernAux_Mutex_lock(&my_mutex.mutex); + + // Access shared data + ++shared_counter; + + // Unlock mutex + KernAux_Mutex_unlock(&my_mutex.mutex); +} diff --git a/include/Makefile.am b/include/Makefile.am index 8755e0f..16539f6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -5,8 +5,8 @@ nobase_include_HEADERS = \ kernaux/arch/x86_64.h \ kernaux/assert.h \ kernaux/macro.h \ - kernaux/mutex.h \ - kernaux/version.h + kernaux/version.h \ + kernaux/generic/mutex.h if ASM_I386 nobase_include_HEADERS += kernaux/asm/i386.h diff --git a/include/kernaux.h.in b/include/kernaux.h.in index eabdfee..834e462 100644 --- a/include/kernaux.h.in +++ b/include/kernaux.h.in @@ -5,9 +5,10 @@ #include #include -#include #include +#include + @comment_line_alloc@#include @comment_line_cmdline@#include @comment_line_console@#include diff --git a/include/kernaux/alloc.h b/include/kernaux/alloc.h index 2a41107..15c25bc 100644 --- a/include/kernaux/alloc.h +++ b/include/kernaux/alloc.h @@ -6,7 +6,7 @@ extern "C" { #endif #include -#include +#include #include diff --git a/include/kernaux/mutex.h b/include/kernaux/generic/mutex.h similarity index 51% rename from include/kernaux/mutex.h rename to include/kernaux/generic/mutex.h index 7dade04..bcd9786 100644 --- a/include/kernaux/mutex.h +++ b/include/kernaux/generic/mutex.h @@ -5,15 +5,14 @@ extern "C" { #endif -#define KERNAUX_MUTEX_EXTRA_DATA_SIZE (32) +#include -typedef void (*KernAux_Mutex_Lock )(void *extra_data); -typedef void (*KernAux_Mutex_Unlock)(void *extra_data); +typedef void (*KernAux_Mutex_Lock )(void *mutex); +typedef void (*KernAux_Mutex_Unlock)(void *mutex); typedef struct KernAux_Mutex { - KernAux_Mutex_Lock lock; - KernAux_Mutex_Unlock unlock; - char extra_data[KERNAUX_MUTEX_EXTRA_DATA_SIZE]; + KernAux_Mutex_Lock KERNAUX_PROTECTED_FIELD(lock); + KernAux_Mutex_Unlock KERNAUX_PROTECTED_FIELD(unlock); } *KernAux_Mutex; void KernAux_Mutex_lock (KernAux_Mutex mutex); diff --git a/include/kernaux/macro.h b/include/kernaux/macro.h index d00f2ce..155687c 100644 --- a/include/kernaux/macro.h +++ b/include/kernaux/macro.h @@ -5,11 +5,18 @@ extern "C" { #endif -#ifdef KERNAUX_PRIVATE_NO -#define KERNAUX_PRIVATE_FIELD(id) id +#ifdef KERNAUX_ACCESS_PRIVATE +# define KERNAUX_PRIVATE_FIELD(id) id +# define KERNAUX_PROTECTED_FIELD(id) id #else -#define KERNAUX_PRIVATE_FIELD(id) _private_##id -#endif +# define KERNAUX_PRIVATE_FIELD(id) _private_##id + +# ifdef KERNAUX_ACCESS_PROTECTED +# define KERNAUX_PROTECTED_FIELD(id) id +# else +# define KERNAUX_PROTECTED_FIELD(id) _protected_##id +# endif +#endif // KERNAUX_ACCESS_PRIVATE #ifdef __cplusplus } diff --git a/src/mutex.c b/src/generic/mutex.c similarity index 75% rename from src/mutex.c rename to src/generic/mutex.c index 9fd4688..16f4e9a 100644 --- a/src/mutex.c +++ b/src/generic/mutex.c @@ -3,14 +3,14 @@ #endif #include -#include +#include void KernAux_Mutex_lock(const KernAux_Mutex mutex) { KERNAUX_ASSERT(mutex); KERNAUX_ASSERT(mutex->lock); - mutex->lock(mutex->extra_data); + mutex->lock(mutex); } void KernAux_Mutex_unlock(const KernAux_Mutex mutex) @@ -18,5 +18,5 @@ void KernAux_Mutex_unlock(const KernAux_Mutex mutex) KERNAUX_ASSERT(mutex); KERNAUX_ASSERT(mutex->unlock); - mutex->unlock(mutex->extra_data); + mutex->unlock(mutex); } diff --git a/tests/test_alloc.c b/tests/test_alloc.c index 8523539..420bc8e 100644 --- a/tests/test_alloc.c +++ b/tests/test_alloc.c @@ -2,7 +2,7 @@ #include "config.h" #endif -#define KERNAUX_PRIVATE_NO +#define KERNAUX_ACCESS_PRIVATE #include diff --git a/tests/test_memmap.c b/tests/test_memmap.c index 98638fc..00d72ca 100644 --- a/tests/test_memmap.c +++ b/tests/test_memmap.c @@ -2,7 +2,7 @@ #include "config.h" #endif -#define KERNAUX_PRIVATE_NO +#define KERNAUX_ACCESS_PRIVATE #include #include