mirror of
https://github.com/clearlinux/graphene.git
synced 2026-09-06 13:51:28 +00:00
Change log (most important only):
- unify CPU context structures - now we have only one version -
`PAL_CONTEXT` - which is shared between LibOS and PALs and it should
depend only on the host architecture (not OS),
- syscalls emulation changed:
- dedicated LibOS stack is now used for syscalls emulation,
- removed one indirection level in syscalls table - now it stores
`shim_do_*` functions directly,
- signal handling - completely rewritten:
- all signal queues use proper locking schemes now,
- signals are handled *only* when returning to the user app from LibOS
or PAL,
- nested signals are now possible,
- the app is allowed to jump out of signal handler with the same
sematics as on normal Linux,
- signal altstack is now fully supported,
- syscall restarting is now supported,
- doing a backtrace from the signal handler works properly,
- disallow injecting host-level signals, with one exception, see
`sys.enable_sigterm_injection` manifest option for more details.
137 lines
3.3 KiB
C
137 lines
3.3 KiB
C
/* SPDX-License-Identifier: LGPL-3.0-or-later */
|
|
/* Copyright (C) 2014 Stony Brook University */
|
|
|
|
#ifndef _SHIM_LOCK_H_
|
|
#define _SHIM_LOCK_H_
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "assert.h"
|
|
#include "pal.h"
|
|
#include "pal_debug.h"
|
|
#include "shim_internal.h"
|
|
#include "shim_thread.h"
|
|
#include "shim_types.h"
|
|
|
|
extern bool lock_enabled;
|
|
|
|
static inline void enable_locking(void) {
|
|
if (!lock_enabled)
|
|
lock_enabled = true;
|
|
}
|
|
|
|
static inline bool lock_created(struct shim_lock* l) {
|
|
return l->lock != NULL;
|
|
}
|
|
|
|
static inline void clear_lock(struct shim_lock* l) {
|
|
l->lock = NULL;
|
|
l->owner = 0;
|
|
}
|
|
|
|
static inline bool create_lock(struct shim_lock* l) {
|
|
l->owner = 0;
|
|
l->lock = DkMutexCreate(0);
|
|
return l->lock != NULL;
|
|
}
|
|
|
|
static inline void destroy_lock(struct shim_lock* l) {
|
|
DkObjectClose(l->lock);
|
|
clear_lock(l);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
#define lock(l) __lock(l, __FILE__, __LINE__)
|
|
static void __lock(struct shim_lock* l, const char* file, int line) {
|
|
#else
|
|
static void lock(struct shim_lock* l) {
|
|
#endif
|
|
if (!lock_enabled) {
|
|
return;
|
|
}
|
|
/* TODO: This whole if should be just an assert. Change it once we are sure that it does not
|
|
* trigger (previous code allowed for this case). Same in unlock below. */
|
|
if (!l->lock) {
|
|
#ifdef DEBUG
|
|
debug("Trying to lock an uninitialized lock at %s:%d!\n", file, line);
|
|
#endif // DEBUG
|
|
__abort();
|
|
}
|
|
|
|
while (!DkSynchronizationObjectWait(l->lock, NO_TIMEOUT))
|
|
/* nop */;
|
|
|
|
l->owner = get_cur_tid();
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
#define unlock(l) __unlock(l, __FILE__, __LINE__)
|
|
static inline void __unlock(struct shim_lock* l, const char* file, int line) {
|
|
#else
|
|
static inline void unlock(struct shim_lock* l) {
|
|
#endif
|
|
if (!lock_enabled) {
|
|
return;
|
|
}
|
|
if (!l->lock) {
|
|
#ifdef DEBUG
|
|
debug("Trying to unlock an uninitialized lock at %s:%d!\n", file, line);
|
|
#endif // DEBUG
|
|
__abort();
|
|
}
|
|
|
|
l->owner = 0;
|
|
DkMutexRelease(l->lock);
|
|
}
|
|
|
|
static inline bool locked(struct shim_lock* l) {
|
|
if (!lock_enabled) {
|
|
return true;
|
|
}
|
|
if (!l->lock) {
|
|
return false;
|
|
}
|
|
return get_cur_tid() == l->owner;
|
|
}
|
|
|
|
#define DEBUG_MASTER_LOCK 0
|
|
|
|
extern struct shim_lock __master_lock;
|
|
|
|
#if DEBUG_MASTER_LOCK == 1
|
|
#define MASTER_LOCK() \
|
|
do { \
|
|
lock(&__master_lock); \
|
|
pal_printf("master lock " __FILE__ ":%d\n", __LINE__); \
|
|
} while (0)
|
|
#define MASTER_UNLOCK() \
|
|
do { \
|
|
pal_printf("master unlock " __FILE__ ":%d\n", __LINE__); \
|
|
unlock(&__master_lock); \
|
|
} while (0)
|
|
#else
|
|
#define MASTER_LOCK() \
|
|
do { \
|
|
lock(&__master_lock); \
|
|
} while (0)
|
|
#define MASTER_UNLOCK() \
|
|
do { \
|
|
unlock(&__master_lock); \
|
|
} while (0)
|
|
#endif
|
|
|
|
static inline bool create_lock_runtime(struct shim_lock* l) {
|
|
bool ret = true;
|
|
|
|
if (!lock_created(l)) {
|
|
MASTER_LOCK();
|
|
if (!lock_created(l))
|
|
ret = create_lock(l);
|
|
MASTER_UNLOCK();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif // _SHIM_LOCK_H_
|