I'm working on a high-reliance implementation of an algorithm for an embedded system.
in main.c:
//.. in main()
int queue_buffer[QUEUE_LEN + 1] = { 0 };
Queue queue;
queue_init(&queue, QUEUE_LEN, queue_buffer);
do_things_on_queue(&queue);
//.. in main()
in queue.c:
void queue_init(Queue *q, int len, int *data) {
q->head = 0;
q->tail = 0;
q->len = len;
q->data = data; // an array of length `len + 1`
}
in queue.h:
typedef struct queue {
int head;
int tail;
int len;
int *data;
} Queue;
I would like to 1. have main.c to not know about Queue; and 2. not use malloc for intializing queue_buffer_ but rather do it statically.
this implies that ideally main.c would be:
//.. in some function
Queue *queue = queue_init(something_eventually);
do_things_with_queue(queue);
//.. in some function
Is it possible to modify queue_init in queue.cto achieve this in C99? If so, what's the best approach?
Tentative Solutions
I am aware of the technique discussed in this post yet they seems unfeasible without using malloc. I know for sure that I will simultaneously have 4 queues at most. This makes me think that I could declare a memory pool for the queues as a static global array of queues of size 4. Is it ok to use global variables in this case?
#KamilKuk suggested to just have queue_init to return the structure itself since QUEUE_LEN is known at compile time. This requires the following:
in queue.c:
Queue queue_init(void) {
Queue q;
q.head = 0;
q.tail = 0;
q.len = QUEUE_LEN;
for (int i=0; i < QUEUE_LEN; i++)
q.data[i] = 0;
return q;
}
in queue.h:
typedef struct queue {
int head;
int tail;
int len;
int data[QUEUE_LEN];
} Queue;
Queue queue_init(void);
This appears to greatly simplify the structure initialization.
However this does not solve the privacy problem, since main.c should know about Queue to initialize this struct.
Thank you.
I would like to 1. have main.c to not know about Queue; and 2. not use
malloc for intializing queue_buffer_ but rather do it statically.
this implies that ideally main.c would be:
//.. in some function
Queue queue = queue_init(something_eventually);
do_things_with_queue(&queue);
//.. in some function
No, your objectives do not imply a solution as described. You cannot declare or use an object of type Queue anywhere that the definition of that type is not visible. That follows directly from the language's rules, but if you want a more meaningful justification then consider that even if main does not access any of the members of Queue, it still needs the definition simply to know how much space to reserve for one.
It's not obvious to me that it serves a useful purpose to make type Queue opaque in main.c (or anywhere), but if that's what you want then in that scope you can forward declare it, never define it, and work only with pointers to it:
typedef struct queue Queue;
// ...
Queue *queue = queue_init(something_eventually);
do_things_with_queue(queue);
For that to work without dynamic memory allocation, the pointed-to Queue objects must have static storage duration, but that does not mean that they need to be globals -- either in the sense of being accessible via a name with external linkage, or in the sense of being declared at file scope.
Additionally, you have the option of allocating the data arrays automatically, as in your example code, so as to not tie up that memory in queues when they are not in use. If you prefer, you can wrap that up in a macro or two for a bit of additional ease of use (left as an exercise).
For example,
queue.h
typedef struct queue Queue;
Queue *queue_init(int queue_size, int queue_data[]);
void queue_release(Queue *queue);
queue.c
#include "queue.h"
struct queue {
int head;
int tail;
int len;
int *data;
};
Queue *queue_init(int queue_len, int queue_data[]) {
// queue_pool has static storage duration and no linkage
static Queue queue_pool[4] = {{0}};
// Find an available Queue, judging by the data pointers
for (Queue *queue = queue_pool;
queue < queue_pool + sizeof(queue_pool) / sizeof(*queue_pool);
queue++) {
if (queue->data == NULL) {
// This one will do. Initialize it and return a pointer to it.
queue->head = 0;
queue->tail = 0;
queue->len = queue_len;
queue->data = queue_data;
return queue;
}
}
// no available Queue
return NULL;
}
void queue_release(Queue *queue) {
if (queue) {
queue->data = NULL;
}
}
main.c
// ... in some function
int queue_data[SOME_QUEUE_LENGTH];
Queue *queue = queue_init(SOME_QUEUE_LENGTH, queue_data);
do_things_with_queue(queue);
queue_release(queue);
// ...
Of course, if you prefer, you can put the queue data directly into the queue structure, as in your tentative solution, and maybe provide a flag there to indicate whether the queue is presently in use. That would relieve users of any need to provide storage, at the cost of tying up the storage for all the elements of all the queues for the whole duration of the program.
The best way to do this is to pass a buffer and its size to the init function, exactly as you already have.
It is a very bad idea to worry about calling a function versus having the data fixed at compile time. Both the execution time and code size for a tiny initialization like this is negligible. Making your code interface awkward just to save a few instructions at startup is not just a waste of effort, it makes the code hard to maintain and risks introducing bugs.
There are a number of embedded systems or libraries that provide a macro which declares both the storage array and the control structure in one go and gives them a name which is known only to the library, and then you have to use a macro to generate the name every time you access the item. For an example of this you might look at osMailQDef in CMSIS-OS. I don't really recommend this method though. It is too easy to get wrong, whereas doing it the usual way is easy to read and any reviewer will be able to spot a mistake straight away.
I would typically do:
// queue.h
#define QUEUE_INIT(data, len) { .len = len, .data = data }
#define QUEUE_INIT_ON_STACK(len) QUEUE_INIT((char[len]){0}, len)
// main.c
static Queue queue = QUEUE_INIT_ON_STACK(QUEUE_LEN + 1);
As for PIMPL idiom, it's easy to implement with descriptors just like file descriptors in LINUX, especially when the count is static.
// queue.h
typedef Queue int;
void do_things_with_queue(Queue);
// queue.c
struct RealQueue { stuff; };
static struct RealQeueue arr[4] = { stuff };
static struct RealQeueue *get_RealQueue(Queue i) {
assert(0 <= i && i < sizeof(arr)/sizeof(*arr));
return &arr[i];
}
void do_things_with_queue(Queue i) {
struct RealQueue *queue = get_RealQueue(i);
}
// main.c
static Queue queue = 1;
// etc.
Or you can break all hell and synchronize alignment between source and header file:
// queue.h
struct Queue {
// This has to be adjusted __for each compiler and environment__
alignas(60) char data[123];
};
#define QUEUE_INIT() { 0xAA, 0xBB, etc.. constant precomputed data }
// queue.c
struct RealQeueue { stuff; };
static_assert(alingof(struct RealQueue) == alignof(struct Queue), "");
static_assert(sizeof(struct RealQueue) == sizeof(struct Queue), "");
void do_things_with_queue(Queue *i) {
struct RealQueue *queue = (struct RealQueue*)i->data;
}
Related
Can anyone tell me why my shared memory data structure (implemented using sys/shm.h) is not being read correctly by pthreads? This is an edited version of my question, with a reduced amount of code. Hopefully its easier to navigate.
Initially, the structure being referenced is created in shared memory space, so two different applications can read and write to it. The aim: to have one application update the shared structure, and the other read it using pthreads. So far everything things are working to an extent. Both applications can read and write to the shared memory, except the pthreads. they don't seem to pick up the modified shared structure?
An overview of the code is below. It is based on a basic runtime system, however, it is not overly complicated. The function executed within the pthreads is:
void* do_work(void *p)
The shared structure is:
typedef struct WL_CTRL_T
Currently all i am trying do is print out the elements of the array. Initially all elements are set to true. Halfway through the execution, using GDB to halt the process, i update the structure from outside, using the other application, by changing elements 0 and 1 to false, then continue to the process. At this i also print out the state of the array from each application via the sequential code, and the print out is correct. However, when the threads are set off, they print the original state of the array, all true...
The structure contains an array of structs, where the active bool field is read by the pthread
I have tried many ways to try and correct this problem, but no joy.
Any advice appreciated, thanks :-)
/*controller api.h*/
typedef struct WL_CTRL_T
{
int targetNumThreads;
int sizeBuf;
int numEntries;
int nextIdx;
thread_state_control_t volatile thread_state_control[THREAD_NUM];
mon_entry_t buffer[];
} wl_ctrl_t;
typedef struct THREADPOOL_T
{
int num_threads;
int qsize;
pthread_t *threads;
todo_t *qhead;
todo_t *qtail;
pthread_mutex_t qlock;
pthread_cond_t q_not_empty;
pthread_cond_t q_empty;
int shutdown;
int dont_accept;
}threadpool_t;
typedef struct TODO_T
{
void (*routine) (void*);
void * arg;
int lock;
struct todo_t* next;
} todo_t;
The function assigned to the pthread
/********************************************************************
*
* do_work:
*
* this is the reusable thread, assigned work via the dispatch
* function.
*
********************************************************************/
void* do_work(void *p)
{
int c = 0;
thread_args_t *thread_args = (thread_args_t*)p;
threadpool_t *pool = thread_args->threadpool;
todo_t* workload;
wl_ctrl_t volatile *wcc = thread_args->wl_ctrl;
while(1)
{
pool->qsize = pool->qsize;
/* while work que is empty, spinlock */
while( pool->qsize == 0)
{
if(c<1)
printf("thread: %d spin-lock \n", thread_args->thread_id);
c++;
}
/* update the threadpool, minus current workload */
workload = pool->qhead;
pool->qsize--;
if(pool->qsize == 0)
{
pool->qhead = NULL;
pool->qtail = NULL;
}
else
{
pool->qhead = workload->next;
}
/* execute workload */
(workload->routine) (workload->arg);
free(workload);
/* check this threads wait state */
printf("In thread: %d\n",wcc->thread_state_control[thread_args->thread_id].active);
}
}
I am working on a program that requires a queue operation to be performed in multi threaded environment.
I am not sure about the thread local storage for a function, not just a global variable
i tried
__thread int head,tail;
__thread int q[MAX_NODES+2];
__thread void enqueue (int x) {
q[tail] = x;
tail++;
color[x] = GRAY;
}
__thread int dequeue () {
int x = q[head];
head++;
color[x] = BLACK;
return x;
}
I got following error
fordp.c:71: error: function definition declared '__thread'
fordp.c:77: error: function definition declared '__thread'
I read somewhere that a function is already thread safe unless its using shared variables so I tried
__thread int head,tail;
__thread int q[MAX_NODES+2];
void enqueue (int x) {
q[tail] = x;
tail++;
color[x] = GRAY;
}
int dequeue () {
int x = q[head];
head++;
color[x] = BLACK;
return x;
}
It did compile with no error, but my execution result was wrong hinting queue didnt work well with multi-threaded platform.
Can someone please explain me what is going on here??
Any help is appreciated.
__thread advises the compiler to create an instance of the variable for every thread.
I doubt that's what you want for the queue, it's head and tail the threads should concurrently operate on, as modifications done by one thread would not be visible by any other thread.
So do not use __thread here, but protect the concurrent access to the global variables, for example using one or more mutexes.
For your reference: http://en.wikipedia.org/wiki/Thread-local_storage
I think you're tackling the problem in the wrong way.
Your problem is that you want to associate a Queue object with a function call (e.g. enqueue).
In C these objects are usually referred to as contexts.
What you did is a variation of a global variable. Using per thread local storage is good for scratch space or actual per thread resources. and this is not the case.
The only option to have thread safety and correctness is to add the context to the function call.
I removed the reference to color to simplify things.
struct queue {
unsigned head, tail;
int q[MAX_NODES+2];
};
void enqueue (struct queue* q, int x) {
q->q[q->tail++] = x;
}
int dequeue (struct queue* q) {
int x = q->q[q->head++];
return x;
}
Note: you should perform checks on pointers and indexes.
I am passing queues like these between source files a.c and b.c
File : a.c
sq[a]=new_queue();
pthread_create(&st[a],NULL,sendPacket,sq[a]);
File : b.c
void *sendPacket(void *queue){
/* here i need to know which queue has come ,determine
the index of queue how can I do it? */
}
Create a more high-level representation of your queue. It seems the queue can be a void * (you're not showing its actual type, i.e. what does the new_queue() call return?), so embed that in a structure while adding the additional parameters:
struct queue_state {
void *queue;
int index;
};
Then instantiate a structure, and pass a pointer to it to the thread function:
struct queue_state qsa = malloc(sizeof *qsa);
if(qsa != NULL)
{
qsa->queue = new_queue();
qsa->index = 4711; /* or whatever */
pthread_create(&st[a], NULL, sendPacket, qsa);
}
Then the thread function can use the struct declaration to access all the fields. Of course, the declaration needs to be in a shared header (say queue.h) which is included from both C files.
Your question description is very rough. But at least from what I understand, you actually need to pass 2 parameters to your function: the (pointer to) queue (which seems an array for me), and the index within this queue.
You may not pack both your parameters in a single variable of type void*. What you may do is declare a struct with all the needed parameters, fill it, and pass a pointer to it to your thread.
Like this (error handling omitted):
struct Params
{
queue* m_Queue;
size_t m_Idx;
};
// ...
Params* pParams = new Params;
pParams->m_Queue = sq;
pParams->m_Idx = a;
pthread_create(&st[a],NULL,sendPacket, pParams);
void *sendPacket(void *pPtr)
{
Params* pParams = (Params*) pPtr;
// ...
delete pParams;
}
Probably it is easier if you just pass the index to the function:
void *sendPacket(int queue_idx) {
queue_t *queue = &sq[queue_idx];
}
If in b.c you have access to sq, you can just pass the index to the queue. Otherwise you can pass a struct containing the actual queue and the index
/*language C code*/
#include "windows.h"
typedef struct object_s
{
SRWLOCK lock;
int data;
} object_t, *object_p; /*own and pointer type*/
void thread(object_p x)
{
AcquireSRWLockExclusive(&x->lock);
//...do something that could probably change x->data value to 0
if(x->data==0)
free(x);
else
ReleaseSRWLockExclusive(&x->lock);
}
void main()
{
int i;
object_p object=(object_p)malloc(sizeof(object_t));
InitializeSRWLock(&object->lock);
for(i=0;i<3;i++)
CreateThread(0,0,thread,object,0);
}
As you can figure out in the codes above, what I have to accomplish is to let one thread conditionally free the object on which the other two may block. Codes above are obviously flawed because if object is set free along with the lock, all blocking threads give us nowhere but wrong.
A solution below
/*language C code*/
#include "windows.h"
typedef struct object_s
{
/*change: move lock to stack in main()*/
int data;
} object_t, *object_p; /*own and pointer type*/
void thread(void * x)
{
struct {
PSRWLOCK l;
object_p o;
} * _x=x;
AcquireSRWLockExclusive(_x->l);
//...do something that could probably change x->data value to 0
if(_x->o->data==0)
free(_x->o);
ReleaseSRWLockExclusive(&x->lock);
}
void main()
{
int i;
SRWLOCK lock; /*lock over here*/
object_p object=(object_p)malloc(sizeof(object_t));
InitializeSRWLock(&lock);
/*pack for thread context*/
struct
{
PSRWLOCK l;
object_p o;
} context={&lock, object};
for(i=0;i<3;i++)
CreateThread(0,0,thread,&context,0);
}
works in this case but not applicable however, in my final project because there is actually a dynamic linked list of objects. By applying this solution it means that there must be a list of locks accordingly, each lock for an object and moreover, when a certain object is set free, its lock must be set free at the same time. There is nothing new compared with the first code section.
Now I wonder if there is an alternative solution to this. Thank you very much!
The solution is to not allocate the lock together with the data. I would suggest that you move the data out of that struct and replace it with a pointer to the data. Your linked list can then free the data first, and then the node, without any problems. Here's some pseudo code:
typedef struct
{
lock_t lock;
int* data_ptr;
} something_t;
void init_something (something_t* thing, ...)
{
thing->lock = init_lock();
thing->data_ptr = malloc(...); // whatever the data is supposed to be
}
void free_something (somthing_t* thing)
{
lock(thing->lock);
free(thing->data_ptr);
thing->data_ptr = NULL;
unlock(thing->lock);
}
...
void linked_list_delete_node (...)
{
free_something(node_to_delete->thing);
free(node_to_delete);
}
...
void thread (void* x)
{
lock(x->lock);
//...do something that could probably change x->data_ptr->data... to 0
if(x->data_ptr->data == 0)
{
free_something(x->data_ptr->data);
}
unlock(x->lock);
}
AcquireSRWLockExclusive(lock);
if(_x->o->data==0)
free(_x);
ReleaseSRWLockExclusive(lock);
As a sidenote, a C program for Windows can never return void. A hosted C program must always return int. Your program will not compile on a C compiler.
Also, CreateThread() expects a function pointer to a function returning a 32-bit value and taking a void pointer as parameter. You pass a different kind of function pointer, function pointer casts aren't allowed in C, nor am I sure what sort of madness Windows will execute if it gets a different function pointer than what it expects. You invoke undefined behavior. This can cause your program to crash or behave in unexpected or random ways.
You need to change your thread function to DWORD WINAPI thread (LPVOID param);
Also I am doing a c implementation and currently have the structure of the queue:
typedef struct queueelem {
queuedata_t data;
struct queueelem *next;
} queueelem_t;
typedef struct queue {
int capacity;
int size;
queueelem_t *head;
queueelem_t *tail;
} queue_t;
queue_t *
queue_init(int capacity)
{
queue_t *q = (queue_t *) malloc(sizeof(queue_t));
q->head = q->tail = NULL;
q->size = 0;
q->capacity = capacity;
return q;
}
int CompareAndExchange (void **a, void *comparand,void *new) {
int success = 0;
pthread_mutex_lock(&CE_MUTEX);
if ((*a) != comparand) {
(*a) = new;
//return TRUE
success = 1;
}
pthread_mutex_unlock(&CE_MUTEX);
//return FALSE
return success;
}
But not sure How to continue, with queue and dequeue functions...
How would the code look like?
Sometime ago, I've found a nice solution to this problem. I believe that it the smallest found so far.
The repository has a example of how use it to create N threads (readers and writers) and make then share a single seat.
I made some benchmarks, on the test example and got the following results (in million ops/sec) :
By buffer size
By number of threads
Notice how the number of threads do not change the throughput.
I think this is the ultimate solution to this problem. It works and is incredible fast and simple. Even with hundreds of threads and a queue of a single position. It can be used as a pipeline beween threads, allocating space inside the queue.
The repository has some early versions written in C# and pascal. Im working to make something more complete polished to show its real powers.
I hope some of you can validate the work or help with some ideas. Or at least, can you break it?
Your pseudo-code can (and most likely does) suffer from the ABA problem, as only the pointer is checked, and not an accompanying unique stamp, you'll find this paper of use in that regard and as a general guide to lock-free queue implementation, with its pitfalls.
When dealing with lock free programing, its also a good idea to read up on Herb Sutter's works, as He gives good, insightful explanations to whats required, why its required and its potential weak points (though beware that some of his older publications/articles where found to contain some hidden/unforseen problems).
and also the recent boost'con talk about this subject :
https://github.com/boostcon/2011_presentations/raw/master/wed/lockfree_2011_slides.pdf
(Leaving this here for now, but see edit.)
Do you know a implementation of lock free queue in C?
I wrote lockless queue recently (http://www.ideone.com/l2QRp). I can't actually guarantee it works correctly, but I can't find any bugs and I've used it in a couple of single threaded programs without any problems, so there's nothing too obvious wrong with it.
Trivial usage example:
queue_t queue;
int val = 42;
queue_init(&queue,sizeof val);
queue_put(&queue,&val);
val = 0;
queue_pop(&queue,&val);
printf("%i\n",val); // 42
queue_destroy(&queue);
Edit:
As #Alexey Kukanov pointed out, queue_pop can fail if tmp is popped,freed,allocated again, and put again between checking for null and swapping:
if(!tmp->next) return errno = ENODATA;
/* can fail here */
} while(!sync_swap(q->head,tmp,tmp->next));
I'm not yet sure how to fix this, but I'll (hopefully) update this once I figure it out. For now, disregard this.
You may try this library it is built in c native. lfqueue
For Example
int* int_data;
lfqueue_t my_queue;
if (lfqueue_init(&my_queue) == -1)
return -1;
/** Wrap This scope in other threads **/
int_data = (int*) malloc(sizeof(int));
assert(int_data != NULL);
*int_data = i++;
/*Enqueue*/
while (lfqueue_enq(&my_queue, int_data) == -1) {
printf("ENQ Full ?\n");
}
/** Wrap This scope in other threads **/
/*Dequeue*/
while ( (int_data = lfqueue_deq(&my_queue)) == NULL) {
printf("DEQ EMPTY ..\n");
}
// printf("%d\n", *(int*) int_data );
free(int_data);
/** End **/
lfqueue_destroy(&my_queue);