Commit d57d12c0 authored by Muktesh Khole's avatar Muktesh Khole Committed by Vikram Narayanan

Fixed crash, basic test passed

Conflicts:
	drivers/Kconfig
	drivers/Makefile
	lib/Kconfig
	lib/Makefile
	lib/thc/thcsync.c
Resolved-by: Vikram Narayanan's avatarVikram Narayanan <vikram186@gmail.com>
parent 5e076560
......@@ -202,4 +202,6 @@ source "drivers/hwtracing/intel_th/Kconfig"
source "drivers/fpga/Kconfig"
source "drivers/thc/Kconfig"
endmenu
......@@ -173,3 +173,5 @@ obj-$(CONFIG_STM) += hwtracing/stm/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_NVMEM) += nvmem/
obj-$(CONFIG_FPGA) += fpga/
obj-$(CONFIG_LAZY_THC) += thc/
......@@ -14,6 +14,9 @@ typedef int errval_t;
#define THC_CANCELED 1
#endif
void thc_init(void);
void thc_done(void);
// The implementation of do..finish relies on shadowing so that
// _fb_info always refers to the closest enclosing do..finish block.
#pragma GCC diagnostic ignored "-Wshadow"
......@@ -57,13 +60,16 @@ typedef int errval_t;
finish_t *_fb_info __attribute__((unused)) = &_fb; \
finish_t *_fb_info_ ## _TAG __attribute__((unused)) = _fb_info; \
void *_fb_curr_stack __attribute__((unused)); \
FORCE_FRAME_POINTER_USE; \
FORCE_FRAME_POINTER_USE; \
GET_STACK_POINTER(_fb_info->old_sp); \
_thc_startfinishblock(_fb_info, _IS_NX); \
printk(KERN_ERR "lcd async DO_FINISH will now execute code"); \
do { _CODE } while (0); \
printk(KERN_ERR "lcd async DO_FINISH finished execurint code\n");\
GET_STACK_POINTER(_fb_curr_stack); \
_thc_endfinishblock(_fb_info, _fb_curr_stack); \
if (_fb_info->old_sp != _fb_curr_stack) { \
printk(KERN_ERR "lcd async DO_FINISH restoring stack pointer\n"); \
RESTORE_OLD_STACK_POINTER(_fb_info->old_sp); \
_thc_pendingfree(); \
} \
......@@ -98,6 +104,7 @@ typedef int errval_t;
#define ASYNC_(_BODY, _C) \
do { \
awe_t _awe; \
printk(KERN_ERR "\nlcd async address of awe: %p\n", &_awe); \
extern void * CONT_RET_FN_NAME(_C) (void); \
\
_awe.status = LAZY_AWE; \
......@@ -105,28 +112,36 @@ typedef int errval_t;
_awe.pts = NULL; \
\
/* Define nested function containing the body */ \
auto void _thc_nested_async(FORCE_ARGS_STACK awe_t *awe) __asm__(NESTED_FN_STRING(_C)); \
__attribute__((noinline,used)) void _thc_nested_async(FORCE_ARGS_STACK awe_t *awe) { \
noinline auto void _thc_nested_async(FORCE_ARGS_STACK awe_t *awe) __asm__(NESTED_FN_STRING(_C)); \
noinline void _thc_nested_async(FORCE_ARGS_STACK awe_t *awe) { \
void *_my_fb = _fb_info; \
_awe.current_fb = _my_fb; \
INIT_LAZY_AWE(awe, &_thc_lazy_awe_marker); \
/* Muktesh code change starts */ \
char *ptr = awe->ebp; \
printk(KERN_ERR "lcd async value of awe ptr in function: %p\n", awe); \
ptr = ptr + 16;\
awe_t **awe_ptr = (awe_t **)ptr;\
printk(KERN_ERR "lcd async value on stack: %p\n", *awe_ptr); \
/* Muktesh Code Change Ends */ \
do { _BODY; } while (0); \
/* If return address is NULLed then we blocked */ \
if (__builtin_return_address(0) == NULL) { \
/* thc_startasync is performed lazily, we should run */ \
/* _thc_endasync if we blocked*/ \
printk(KERN_ERR "lcd async calling into endasync\n"); \
_thc_endasync(_my_fb, __builtin_frame_address(0)+(2*__WORD_SIZE));\
} \
/* Otherwise, return */ \
printk(KERN_ERR "lcd async nested fn complete now returning\n"); \
RETURN_CONT(CONT_RET_FN_STRING(_C)); \
debug_printf("ERROR: "NESTED_FN_STRING(_C)" should never returned!"); \
} \
SCHEDULE_CONT(&_awe, _thc_nested_async); \
__asm__ volatile ( \
" .globl " CONT_RET_FN_STRING(_C) "\n\t" \
" " CONT_RET_FN_STRING(_C) ": \n\t" \
); \
\
printk(KERN_ERR "lcd async ASYNC Complete\n"); \
} while (0)
#else // EAGER_THC
......
......@@ -360,7 +360,22 @@ extern int _end_text_nx;
#define SCHEDULE_CONT(_AWE_PTR, NESTED_FUNC) \
({ \
KILL_CALLEE_SAVES(); \
uint64_t savedRAX; \
__asm__ __volatile__( \
"movq %%rbx, %0\n\t" \
"movq %1, %%rbx\n\t" \
"push %%rbx\n\t" \
"movq %0, %%rbx\n\t" \
:"=r"(savedRAX) \
:"r"(_AWE_PTR) \
); \
NESTED_FUNC(FORCE_ARGS_STACK_CALL _AWE_PTR); \
__asm__ __volatile__( \
"movq %%rbx, %0\n\t" \
"pop %%rbx\n\t" \
"movq %0, %%rbx\n\t" \
:"=r"(savedRAX) \
); \
})
#define CALL_CONT(_FN,_ARG) \
......
......@@ -63,6 +63,8 @@ struct sched_param {
#ifdef CONFIG_HAVE_LCD
struct lcd;
struct cptr_cache;
#endif
#ifdef CONFIG_LAZY_THC
struct ptstate_t;
#endif
......@@ -1472,6 +1474,8 @@ struct task_struct {
#ifdef CONFIG_HAVE_LCD
struct lcd *lcd;
struct cptr_cache *cptr_cache;
#endif
#ifdef CONFIG_LAZY_THC
struct ptstate_t *ptstate; /* per thread state */
#endif
#ifdef CONFIG_SMP
......
......@@ -6,6 +6,7 @@
//#include <stdint.h>
//#include <stdlib.h>
#include <lcd-domains/types.h>
#include <linux/sched.h>
#ifndef BARRELFISH
typedef int errval_t;
......
......@@ -6,9 +6,10 @@
/***********************************************************************/
typedef struct ptstate_t PTState_t;
typedef struct stack_t stack_t;
typedef struct thcstack_t thcstack_t;
typedef struct finish_t finish_t;
struct thc_latch;
typedef void (*THCIdleFn_t)(void *);
// Definition of an AWE, asynchronous work element. This definition must
// match the assembly-language definitions at the bottom of thc.c which
// access fields in the AWE structure.
......@@ -42,8 +43,8 @@ struct awe_t {
// Fields used by the runtime system to link together AWEs, e.g.,
// on a thread's run-queue, or on a list of waiters on a
// synchronization object.
awe_t *prev;
awe_t *next;
struct awe_t *prev;
struct awe_t *next;
};
/***********************************************************************/
......@@ -66,22 +67,22 @@ struct finish_list_t {
struct finish_t {
void *old_sp; /* stack pointer when entering do {} finish */
unsigned long count;
awe_t *finish_awe;
struct awe_t *finish_awe;
int fb_kind;
int cancel_requested;
finish_list_t start_node;
finish_list_t end_node;
finish_t *enclosing_fb;
void *enclosing_lazy_stack;
cancel_item_t *cancel_item;
struct cancel_item_t *cancel_item;
};
/***********************************************************************/
// Per-thread runtime system state
struct stack_t {
stack_t *next;
struct thcstack_t {
struct thcstack_t *next;
};
struct ptstate_t {
......@@ -89,8 +90,8 @@ struct ptstate_t {
// Thread-local fields: .............................................
// Head/tail sentinels of the dispatch list
awe_t aweHead;
awe_t aweTail;
struct awe_t aweHead;
struct awe_t aweTail;
// Immediately-enclosing finish block for the currently running code
finish_t *current_fb;
......@@ -119,10 +120,10 @@ struct ptstate_t {
void *pendingFree;
// AWE to enter for the dispatch loop on this thread
awe_t dispatch_awe;
struct awe_t dispatch_awe;
// Free stacks for re-use
stack_t *free_stacks;
struct thcstack_t *free_stacks;
#ifndef NDEBUG
......@@ -157,8 +158,8 @@ struct ptstate_t {
// Head/tail sentinels of the remote dispatch list on which other
// threads place AWEs that they have unblocks but which belong to
// this thread
awe_t aweRemoteHead;
awe_t aweRemoteTail;
struct awe_t aweRemoteHead;
struct awe_t aweRemoteTail;
};
typedef void (*THCContFn_t)(void *cont, void *args);
......@@ -171,8 +172,8 @@ void _thc_endasync(void *f, void *s);
void _thc_startfinishblock(finish_t *fb, int fb_kind);
void _thc_endfinishblock(finish_t *fb, void *stack);
void _thc_do_cancel_request(finish_t *fb);
void _thc_callcont(awe_t *awe, THCContFn_t fn, void *args) __attribute__((returns_twice));
int _thc_schedulecont(awe_t *awe) __attribute__((returns_twice));
void _thc_callcont(struct awe_t *awe, THCContFn_t fn, void *args) __attribute__((returns_twice));
int _thc_schedulecont(struct awe_t *awe) __attribute__((returns_twice));
void _thc_lazy_awe_marker(void);
void _thc_pendingfree(void);
......
......@@ -4,7 +4,7 @@
#ifdef BARRELFISH
#include <barrelfish/barrelfish.h>
#endif
#include <assert.h>
//#include <assert.h>
// Configuration options:
......@@ -20,7 +20,7 @@
// Lists of waiters
struct thc_waiter {
awe_t *waiter;
struct awe_t *waiter;
struct thc_waiter *next;
};
......@@ -48,7 +48,7 @@ static inline void thc_latch_acquire(struct thc_latch *l) {
}
static inline void thc_latch_release(struct thc_latch *l) {
assert(l->c == 1);
//assert(l->c == 1);
l->c = 0;
}
......
obj-$(CONFIG_LAZY_THC) += thc.o
thc-y := main.o thc.o thcsync.o
obj-$(CONFIG_LAZY_THC) += async.o
async-y := main.o thc.o thcsync.o
......@@ -8,14 +8,35 @@
#include <linux/init.h>
#include <linux/module.h>
#include <lcd-domains/thc.h>
#include <lcd-domains/thcinternal.h>
#include <lcd-domains/thcsync.h>
void foo1(void);
void foo2(void);
bool testFlag = false;
int __init api_init(void)
void foo1(void) {
printk(KERN_ERR "lcd async entering foo1");
while (testFlag == false) {
printk(KERN_ERR "lcd async yielding to foo2");
THCYield();
}
printk(KERN_ERR "lcd async foo1 complete");
}
void foo2(void) {
printk(KERN_ERR "lcd async entering foo2");
testFlag = true;
}
static int __init api_init(void)
{
DO_FINISH(ASYNC(foo1();foo2();););
printk(KERN_ERR "lcd async entering module");
return 0;
}
void __exit api_exit(void)
static void __exit api_exit(void)
{
printk(KERN_ERR "lcd async exiting module");
return;
......
This diff is collapsed.
......@@ -2,20 +2,12 @@
// Synchronization primitives
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifdef BARRELFISH
#include <thc/thc.h>
#elif defined(_MSC_VER)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <thc/thc.h>
#else
#include "thc.h"
#endif
//#include <stdlib.h>
//#include <stdio.h>
//#include <string.h>
//#include <assert.h>
#include <lcd-domains/thc.h>
#define NOT_REACHED assert(0 && "Not reached")
#define DEBUGPRINTF debug_printf
......@@ -100,17 +92,18 @@ static void thc_sem_p_x_cancel_fn(void *c) {
} else {
// Cancelation won any wake/cancel race: remove the waiter so
// that it cannot receive a subsequent V.
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Looking for wait-queue entry %p\n", cinf->waiter_info));
cinf -> was_canceled = 1;
struct thc_waiter **qptr = &(cinf->sem->q);
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Looking for wait-queue entry %p\n", cinf->waiter_info));
cinf -> was_canceled = 1;
while ((*qptr) != NULL && *qptr != cinf->waiter_info) {
qptr = &((*qptr)->next);
}
assert((*qptr) != NULL && "Could not find waiter entry on cancel");
//assert((*qptr) != NULL && "Could not find waiter entry on cancel");
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Removed wait-queue entry (now %p -> %p)\n", qptr, (*qptr)->next));
*qptr = (*qptr)->next;
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Waking p_x operation\n"));
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Waking p_x operation\n"));
THCSchedule(cinf->waiter_info->waiter);
}
......@@ -118,12 +111,12 @@ static void thc_sem_p_x_cancel_fn(void *c) {
}
errval_t thc_sem_p_x(thc_sem_t *s) {
int canceled = 0;
// Return THC_CANCELED if already requested
if (THCIsCancelRequested()) {
return THC_CANCELED;
}
int canceled = 0;
thc_latch_acquire(&s->l);
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_sem_p_x(%p) %d\n", s, s->val));
if (s->val == 0) {
......@@ -160,13 +153,14 @@ void thc_sem_v(thc_sem_t *s) {
thc_latch_acquire(&s->l);
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_sem_v(%p)\n", s));
if (s->q != NULL) {
awe_t *to_wake;
struct thc_waiter *w = s->q;
s->q = w->next;
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_sem_v waking %p\n", w));
// NB: unlink the waiter structure before scheduling: they may
// run immediately on a concurrent thread, and de-allcoate the
// waiter structure.
awe_t *to_wake = w->waiter;
to_wake = w->waiter;
// NULL out waiter; signals to the cancelation function
// that they lost a wake-up/cancel race
w->waiter = NULL;
......@@ -264,19 +258,20 @@ static void thc_condvar_wait_x_cancel_fn(void *c) {
// return.
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Cancelation lost wake/cancel race\n"));
} else {
// Cancelation won any wake/cancel race: remove the waiter so
struct thc_waiter **qptr = &(cinf->cv->q);
// Cancelation won any wake/cancel race: remove the waiter so
// that it cannot receive a subsequent notify.
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Looking for wait-queue entry %p\n", cinf->waiter_info));
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Looking for wait-queue entry %p\n", cinf->waiter_info));
cinf -> was_canceled = 1;
struct thc_waiter **qptr = &(cinf->cv->q);
while ((*qptr) != NULL && *qptr != cinf->waiter_info) {
qptr = &((*qptr)->next);
}
assert((*qptr) != NULL && "Could not find waiter entry on cancel");
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Removed wait-queue entry (now %p -> %p)\n", qptr, (*qptr)->next));
//assert((*qptr) != NULL && "Could not find waiter entry on cancel");
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Removed wait-queue entry (now %p -> %p)\n", qptr, (*qptr)->next));
*qptr = (*qptr)->next;
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Waking condvar_wait_x operation\n"));
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Waking condvar_wait_x operation\n"));
THCSchedule(cinf->waiter_info->waiter);
}
......@@ -284,38 +279,38 @@ static void thc_condvar_wait_x_cancel_fn(void *c) {
}
errval_t thc_condvar_wait_x(thc_condvar_t *cv, thc_lock_t *lock) {
// Return THC_CANCELED if already requested
if (THCIsCancelRequested()) {
return THC_CANCELED;
}
int canceled = 0;
struct thc_cv_cancel_info cinf;
cancel_item_t ci;
struct thc_waiter w;
thc_condvar_wait0_info_t info;
// Return THC_CANCELED if already requested
if (THCIsCancelRequested()) {
return THC_CANCELED;
}
thc_latch_acquire(&cv->l);
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_condvar_wait(%p,%p)\n", cv, lock));
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_condvar_wait(%p,%p)\n", cv, lock));
cinf.waiter_info = &w;
cinf.cv = cv;
cinf.was_canceled = 0;
w.next = cv->q;
cv->q = &w;
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_condvar_wait sleeping %p\n", &w));
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_condvar_wait sleeping %p\n", &w));
info.cv = cv;
info.lock = lock;
THCAddCancelItem(&ci, &thc_condvar_wait_x_cancel_fn, (void*)&cinf);
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Adding cancel item\n"));
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Adding cancel item\n"));
THCSuspendThen(&w.waiter, thc_condvar_wait0, (void*)&info); // Sleep ......
canceled = cinf.was_canceled;
if (!canceled) {
if (!THCCancelItemRan(&ci)) {
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Removing cancel item\n"));
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "Removing cancel item\n"));
THCRemoveCancelItem(&ci);
}
}
DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_condvar_wait retaking lock %p\n", lock));
//DEBUG_SYNC(DEBUGPRINTF(DEBUG_SYNC_PREFIX "thc_condvar_wait retaking lock %p\n", lock));
thc_latch_acquire(&cv->l);
thc_lock_acquire(lock);
thc_latch_release(&cv->l);
......@@ -339,8 +334,9 @@ void thc_condvar_signal(thc_condvar_t *cv) {
}
void thc_condvar_broadcast(thc_condvar_t *cv) {
struct thc_waiter *w;
thc_latch_acquire(&cv->l);
struct thc_waiter *w = cv->q;
w = cv->q;
while (w != NULL) {
awe_t *to_wake = w->waiter;
// NULL out waiter; signals to the cancelation function
......@@ -527,7 +523,7 @@ uint64_t thc_seq_ticket(thc_seq_t *seq) {
break;
}
} while(1);
assert((result >= 0) && "URK! Sequencer wrapped");
//assert((result >= 0) && "URK! Sequencer wrapped");
return result;
#endif
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment