Generic mutex (#77)

This commit is contained in:
Alex Kotov 2022-06-21 00:28:35 +03:00 committed by GitHub
parent c99cce166e
commit 4ef44158c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 126 additions and 24 deletions

1
.gitignore vendored
View File

@ -110,6 +110,7 @@
/examples/cmdline
/examples/fprintf
/examples/fprintf_va
/examples/generic_mutex
/examples/memmap
/examples/ntoa
/examples/panic

View File

@ -1,6 +1,9 @@
2022-06-20 Alex Kotov <kotovalexarian@gmail.com>
* 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 <kotovalexarian@gmail.com>

View File

@ -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

View File

@ -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 `<kernaux.h>` and
`<kernaux/*.h>` 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

View File

@ -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 #
##########

76
examples/generic_mutex.c Normal file
View File

@ -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 <kernaux/generic/mutex.h>
#include <pthread.h>
typedef struct MyMutex {
struct KernAux_Mutex mutex;
pthread_mutex_t pthread_mutex;
} *MyMutex;
struct MyMutex MyMytex_create();
//============
// my_mutex.c
//============
#include <kernaux/generic/mutex.h>
#include <pthread.h>
#include <stdlib.h>
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);
}

View File

@ -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

View File

@ -5,9 +5,10 @@
#include <kernaux/assert.h>
#include <kernaux/macro.h>
#include <kernaux/mutex.h>
#include <kernaux/version.h>
#include <kernaux/generic/mutex.h>
@comment_line_alloc@#include <kernaux/alloc.h>
@comment_line_cmdline@#include <kernaux/cmdline.h>
@comment_line_console@#include <kernaux/console.h>

View File

@ -6,7 +6,7 @@ extern "C" {
#endif
#include <kernaux/macro.h>
#include <kernaux/mutex.h>
#include <kernaux/generic/mutex.h>
#include <stddef.h>

View File

@ -5,15 +5,14 @@
extern "C" {
#endif
#define KERNAUX_MUTEX_EXTRA_DATA_SIZE (32)
#include <kernaux/macro.h>
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);

View File

@ -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
}

View File

@ -3,14 +3,14 @@
#endif
#include <kernaux/assert.h>
#include <kernaux/mutex.h>
#include <kernaux/generic/mutex.h>
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);
}

View File

@ -2,7 +2,7 @@
#include "config.h"
#endif
#define KERNAUX_PRIVATE_NO
#define KERNAUX_ACCESS_PRIVATE
#include <kernaux/alloc.h>

View File

@ -2,7 +2,7 @@
#include "config.h"
#endif
#define KERNAUX_PRIVATE_NO
#define KERNAUX_ACCESS_PRIVATE
#include <kernaux/assert.h>
#include <kernaux/memmap.h>