CreateThread wrapper function - c

I am currently working on a project where we have a C thread implementation for UNIX systems using pthreads. Now we want to be able to run this entire project on Windows as well, and I am translating all the threading for WIN32. Now I encountered a problem for which I could not come up with a decent solution.
I have the thrd_create() function:
static inline int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
Args* args = malloc(sizeof(Args));
args->arg = arg;
args->function = func;
*thr = CreateThread(NULL, 0, wrapper_function, (LPVOID) args, 0, NULL);
if (!*thr) {
free (args);
return thrd_error;
}
return thrd_success;
}
This function is supposed to create a new thread, and the user provides a start function. For convenience, I would like to leave the implementation that calls thrd_create() untouched if possible. For this reason, I created a wrapper_function:
static inline DWORD wrapper_function(LPVOID arg) {
Args * args;
args = (Args*) arg;
DWORD res = args->function(args->arg); //This does obviously not work
return res;
}
My question is: What DWORD should my wrapper function return? The function provided by the user for the pthread implementation has void return type, so I won't get any result from that. Any suggestions?
EDIT
Args looks like this:
struct Args {
void (*function)(void * aArg);
void* arg;
};
typedef struct Args Args;

According to manuals it is better to stick to a correct signature and use return value:
Windows
Pthreads
The other matter of concern would be the lifetime of args, I'd say the best way is for a caller to clean up, so they need to be tracked with your thread until it terminates.
An approximate API could be something along the lines of the following:
/* Your general error codes enumeration
* which should probably reside in a general
* header
*/
typedef enum {
OK = 0,
// Your application specific error codes
} error_t;
#ifdef _WIN32
#include <Windows.h>
typedef HANDLE thread_handle_t;
#else // assume pthreads
#include <pthread.h>
typedef pthread_t thread_handle_t;
#endif
typedef error_t(*entry_func_t)(void*);
typedef struct {
entry_func_t func;
void *args;
error_t _result;
thread_handle_t _handle;
} thread_t;
// returns OK(0) on success
// returns error code indicating a problem
error_t thread_create(thread_t *t);
An aproximate implementation would be:
#ifdef _WIN32
DWORD _win_entry_f(void *args) {
thread_t *t = args;
t->_result = t->func(t->args);
return 0; // Or some other Windows-specific value
}
error_t thread_create(thread_t *t) {
error_t err = OK;
if(!(t->_handle = ThreadCreate(NULL, 0, _win_entry_f, t, 0, NULL))) {
switch (GetLastError()) {
// Populate error with code
}
}
return err;
}
#else
void * _pthread_entry_f(void *args) {
thread_t *t = args;
t->_result = t->func(t->args);
return NULL; // Or some other pthreads specific value
}
error_t thread_create(thread_t *t, entry_func_t func, void *args) {
error_t err = OK;
switch(pthread_create(&t->_handle, NULL, _pthread_entry_f, t)) {
case 0: break;
// other cases populate err
}
return err;
}
#endif
Invokation would look somewhat like this.
error_t func(void* args) {
return OK;
}
.....................
thread_t t = { .func = func, .args = NULL };
thread_create(&t);
Obviously you'll need to implement your own cancelation, result collection, join, ...

Related

How to wrap function pointer in plain C

Is it possible to "wrap" a function pointer in C somehow, similar to what you would do with a lambda in C#?
Actual problem I am having is:
I have a couple of functions with different parameters:
// more than two in actual code
void DoStuff(void) { ... }
void DoOtherStuff(int) { ... }
...and I want to create a couple of threads to run these in a loop:
// this won't work because it expects a LPTHREAD_START_ROUTINE,
// which is int(*fn)(void*)
tHnd1 = CreateThread(NULL, 0, &DoStuff, NULL, 0, &tId);
tHnd2 = CreateThread(NULL, 0, &DoOtherStuff, NULL, 0, &tId);
In C#/C++ I would use a lambda, or a pointer to a method which would call the other one, but I have no clue how to do this in C, unless I manually create wrapper functions:
int CallDoStuff(void *dummy) { DoStuff(); return 0; }
int CallDoOtherStuff(void *dummy) { DoOtherStuff(42); return 0; }
Is there any other way to avoid doing this step?
Nope, there's really no other way than to create the wrapper functions. And remember they have to return a value as well. If you don't wrap (or forget to return a (dummy) value) you will have UB.
You can create structure which will contain function type, function pointer and arguments if needed. Thread function would have to check function type and then call function using appropriate signature and pass parameters stored in structure. You can also create helper functions used to create these structures to simplify coding. Below is example code for two possible function types (with void and int arg):
#include <stdio.h>
#include <stdlib.h>
/* Few types needed to store function pointer and arguments in struct */
typedef enum FuncType
{
F_Void,
F_Int,
} FuncType;
typedef void(*VoidFuncPtr)(void);
typedef void(*IntFuncPtr)(int);
typedef struct FuncWrapper
{
FuncType funcType;
union
{
VoidFuncPtr voidFunc;
IntFuncPtr intFunc;
};
union
{
int intArg;
};
} FuncWrapper;
/* Thread func which can handle different functions */
void ThreadFunc(void* arg)
{
FuncWrapper* wrapper = (FuncWrapper*)arg;
switch (wrapper->funcType)
{
case F_Void:
wrapper->voidFunc();
break;
case F_Int:
wrapper->intFunc(wrapper->intArg);
break;
}
free(wrapper);
}
/* Helper functions used to create FuncWrapper instances */
FuncWrapper* wrapVoidFunc(VoidFuncPtr func)
{
FuncWrapper* wrapper = (FuncWrapper*)malloc(sizeof(FuncWrapper));
wrapper->funcType = F_Void;
wrapper->voidFunc = func;
return wrapper;
}
FuncWrapper* wrapIntFunc(IntFuncPtr func, int arg)
{
FuncWrapper* wrapper = (FuncWrapper*)malloc(sizeof(FuncWrapper));
wrapper->funcType = F_Int;
wrapper->intFunc = func;
wrapper->intArg = arg;
return wrapper;
}
/* Dummy StartThread func, which simply calls passed in function */
typedef void(*ThreadFuncPtr)(void*);
void StartThread(ThreadFuncPtr funcPtr, void* data)
{
funcPtr(data);
}
/* Functions which will be called */
void myVoidFunction(void)
{
printf("myVoidFunction called\n");
}
void myIntFunction(int arg)
{
printf("myIntFunction called, arg = %d\n", arg);
}
/* Finally the main func */
int main()
{
StartThread(ThreadFunc, wrapVoidFunc(myVoidFunction));
StartThread(ThreadFunc, wrapIntFunc(myIntFunction, 22));
return 0;
}

kprobe, function scheduling - processor lockup - Linux kernel

I've a function I wrote in order to run a given function on all processors. It works perfectly well in all cases except the following case:
When I try to use it within a kprobe that I registered.
Here's some code:
static DEFINE_MUTEX(entryMutex);
static struct kretprobe my_kprobe = {
.entry_handler = (kprobe_opcode_t *) NULL,
.handler = (kprobe_opcode_t *) process_entry_callback,
.maxactive = 1000,
.data_size = 0
};
static int driver_init(void)
{
my_kprobe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("sys_execve");
if ((ret = register_kretprobe(&my_kprobe)) < 0)
return -1;
return 0;
}
void foo(void* nothing)
{
printk("In foo\n");
}
static int process_entry_callback(struct kretprobe_instance* instance, struct pt_regs* regs)
{
mutex_lock(&entryMutex);
for(int i = 0; i < 4; ++i) // assumes there are 4 processors
run_func(foo, NULL, i);
mutex_unlock(&entryMutex);
return 0;
}
void run_func_wrap(struct function_data* data)
{
data->func(data->context);
wake_up_process(data->waiting_task);
*(data->condition) = TRUE;
}
void run_func(SCHEDULED_FUNC func, void *context, int processor)
{
struct function_data data;
struct task_struct* th;
BOOLEAN condition = FALSE;
wait_queue_head_t queue;
init_waitqueue_head(&queue);
data.func = func;
data.waiting_task = current;
data.context = context;
data.condition = &condition;
th = kthread_create(sched_func_wrap, &data, "th");
kthread_bind(th, processor);
wake_up_process(th);
wait_event(queue, condition);
}
F
After the call to 'run_func' in process_entry_callback I can no longer run any programs. Every time I start a new program it just stuck. After a while I get 'processor lockup' warning in the system log.
I suspect that it has something to do with the IRQ levels.
Any suggestions ?
EDIT:
It also happens when using the following function:
smp_call_function_single
which can be found in smp.c # the Linux kernel source code.
instead of my function:
run_func

pthread_mutex_lock gets stuck

The revelant code may be found here: http://pastebin.com/VbhtQckm
The problem is at line
85. pthread_mutex_lock(ID_retrieval_pool->info->lock);
I'm running the server and it's getting stuck at lock. The memory is allocated, I'm initializing the mutex and it's the only thread who's owning that shared memory.
I did debug with GDB and Valgrind using helgrind tool but did not find any clue.
Possible problems which think may cause this:
mutex is not being initialized (I'm using a block is shared memory which I'm initializing as a mutex);
deadlock? in the man page https://www.sourceware.org/pthreads-
win32/manual/pthread_mutex_init.html says this can cause this;
Please note that this code is for learning purpose.
Edit, the code is:
// common_header.h + common_header.c
#ifndef DATA_TYPES_H
#define DATA_TYPES_H
#include <pthread.h>
#include <errno.h>
#define RETREIVE_ID_KEY 1
typedef enum {
SHM_State_None,
SHM_State_ID_Available,
SHM_State_ID_Not_Available,
} SHM_State;
typedef struct {
pthread_mutex_t *lock; // locked if any thread is modifying data
SHM_State state;
} data_state;
typedef int shmid_t;
typedef struct data_pool {
data_state *info;
shmid_t shm_id;
} data_pool;
// other data structures
extern data_state * data_state_initialize_by_setting_address(void *address)
{
data_state *data = (data_state *)address;
data->lock = (pthread_mutex_t *)address;
pthread_mutex_init(data->lock, NULL);
data->state = SHM_State_None;
return data;
}
extern data_pool * data_pool_initialize_by_setting_address(void *address)
{
data_pool *data = (data_pool *)address;
data->info = data_state_initialize_by_setting_address(address);
data->shm_id = 0; // invalid though, the structure's client has to set a valid one
return data;
}
// other initialization functions
#endif // DATA_TYPES_H
///----------------------------------------------------------------------------------------\\\
// main.c -- Server
#include "common_header.h"
#define SHM_INVALID_ADDRESS (void *)-1
#define SHMGET_RW_FLAGS 0666
#define SHMAT_RW_FLAGS 0
bool initialize_data();
static data_pool *ID_retrieval_pool = NULL;
int main(int argc, char *argv[])
{
if (!initialize_data()) {
return EXIT_FAILURE;
}
// Do other stuff
return EXIT_SUCCESS;
}
bool initialize_data()
{
// some irrelevant initialization code
shmid_t shm_ID = shmget(RETREIVE_ID_KEY,
sizeof(data_pool),
IPC_CREAT | SHMGET_RW_FLAGS);
void *shm_address = shmat(shm_ID, NULL, SHMAT_RW_FLAGS);
if (shm_address == SHM_INVALID_ADDRESS) {
return false;
}
ID_retrieval_pool = data_pool_initialize_by_setting_address(shm_address);
pthread_mutex_lock(ID_retrieval_pool->info->lock);
ID_retrieval_pool->shm_id = get_shared_ID();
ID_retrieval_pool->info->state = SHM_State_ID_Available;
pthread_mutex_unlock(ID_retrieval_pool->info->lock);
// other initialization code
return true;
}
You have an interesting and incorrect way of initializing the mutex:
data->lock = (pthread_mutex_t *)address; /* address == &data */
pthread_mutex_init(data->lock, NULL);
In your code address is the address of the outer struct: this does not actually allocate a usable block of memory.
I suggest you just make the mutex non-pointer and then initialize it:
/* In the struct. */
pthread_mutex_t lock;
/* In your function. */
pthread_mutex_init(&data->lock, NULL);

How to check if stdout has been redirected to NUL on Windows (a.k.a. /dev/null on Linux)?

How can I check if my program's stdout has been redirected to NUL?
That way I can avoid outputting data since it's pointless.
I mainly need this for Windows, but if you have a Linux solution, it might be helpful for others in the future, so feel free to post that as well.
There are probably other ways to do this (and it wouldn't be a surprise if there turns out to be a proper function for it I've overlooked), but here's one way:
enum
{
Output_Console,
Output_File,
Output_NUL,
};
bool GetOutputHandleType(int* piType)
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
if (h)
{
BY_HANDLE_FILE_INFORMATION fi;
if (GetFileInformationByHandle(h, &fi))
{
*piType = Output_File;
return true;
}
if (GetLastError() == ERROR_INVALID_FUNCTION)
{
*piType = Output_NUL;
return true;
}
if (GetLastError() == ERROR_INVALID_HANDLE)
{
*piType = Output_Console;
return true;
}
}
return false;
}
I figured it out myself. It's annoying.
#include <Windows.h>
#include <io.h>
#pragma comment(lib, "ntdll.lib") // can instead use GetProcAddress (below)
extern "C" NTSTATUS __stdcall NtQueryVolumeInformationFile(
HANDLE FileHandle, struct _IO_STATUS_BLOCK *IoStatusBlock,
void *FsInformation, unsigned long Length,
enum _FSINFOCLASS FsInformationClass);
bool isdevnull(FILE *file)
{
struct FILE_FS_DEVICE_INFORMATION
{ unsigned long DeviceType, Characteristics; } fsinfo;
struct { void *info, *status; } iosb;
typedef NTSTATUS (__stdcall *PNTQIF)(
HANDLE FileHandle, struct _IO_STATUS_BLOCK *IoStatusBlock,
void *FsInformation, unsigned long Length,
enum _FSINFOCLASS FsInformationClass);
PNTQIF const ntqif =
true // True if you have ntdll.lib, false otherwise
? NtQueryVolumeInformationFile
: (PNTQIF) GetProcAddress(
GetModuleHandle(TEXT("ntdll.dll")),
"NtQueryVolumeInformationFile");
return ntqif(
(HANDLE) _get_osfhandle(_fileno(stdout)),
(struct _IO_STATUS_BLOCK *)&iosb,
&fsinfo, sizeof(fsinfo),
(enum _FSINFOCLASS)4
) == 0 && fsinfo.DeviceType == 0x00000015 /*FILE_DEVICE_NULL*/;
}
int main()
{
bool b = isdevnull(stdout);
}

What does the usage of `(void)struct_pointer`?

I am now reading a project and find some of the codes hard to understand, like below:
struct mcachefs_metadata_t* mdata_root;
...
mcachefs_metadata_release(mdata_root);
And the definition of mcachefs_metadata_release is as below:
void
mcachefs_metadata_release(struct mcachefs_metadata_t* mdata)
{
(void) mdata;
mcachefs_metadata_unlock ();
}
And the definitioin of mcachefs_metadata_unlock is as below:
#define mcachefs_metadata_unlock() mcachefs_mutex_unlock ( &mcachefs_metadata_mutex, "metadata", __CONTEXT );
Then, the mcachefs_mutex_unlock function:
void
mcachefs_mutex_unlock(struct mcachefs_mutex_t* mutex, const char* name,
const char* context)
{
int res;
...
mutex->owner = 0;
mutex->context = NULL;
res = pthread_mutex_unlock(&(mutex->mutex));
if (res == 0)
{
return;
}
...
}
I could not understand what does the (void) mdata; mean in the
mcachefs_metadata_release function. What does the usage of it?
It's for suppressing unused argument: mdata compiler warnings. Rather bad practice, by the way.

Resources