Uniform sequence at start of source files - copyright claim - license - file comment - header guard - lumiera includes - library / system includes Lumiera uses Brittish spelling. Add an according note to the styleguide.
284 lines
8.4 KiB
C
284 lines
8.4 KiB
C
/*
|
|
THREADS.h - Helper for managing threads
|
|
|
|
Copyright (C) Lumiera.org
|
|
2008, Christian Thaeter <ct@pipapo.org>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of
|
|
the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
#ifndef BACKEND_THREADS_H
|
|
#define BACKEND_THREADS_H
|
|
|
|
#include "lib/condition.h"
|
|
|
|
#include <nobug.h>
|
|
|
|
|
|
|
|
typedef struct lumiera_thread_struct lumiera_thread;
|
|
typedef lumiera_thread* LumieraThread;
|
|
|
|
/** Helper macro used for an enum string trick */
|
|
#define LUMIERA_THREAD_CLASSES \
|
|
/** mostly idle, low latency **/ \
|
|
LUMIERA_THREAD_CLASS(INTERACTIVE) \
|
|
/** busy at average priority **/ \
|
|
LUMIERA_THREAD_CLASS(WORKER) \
|
|
/** busy, soft realtime, high priority **/ \
|
|
LUMIERA_THREAD_CLASS(URGENT) \
|
|
/** high latency, background jobs **/ \
|
|
LUMIERA_THREAD_CLASS(BATCH) \
|
|
/** Something to do when there is really nothing else to do **/ \
|
|
LUMIERA_THREAD_CLASS(IDLE)
|
|
|
|
/** Macro for enum string trick: expands as an enum of thread classes */
|
|
#define LUMIERA_THREAD_CLASS(name) LUMIERA_THREADCLASS_##name,
|
|
|
|
|
|
|
|
/**
|
|
* Thread classes.
|
|
* We define some 'classes' of threads for different purposes to abstract
|
|
* priorities and other attributes.
|
|
*/
|
|
enum lumiera_thread_class
|
|
{
|
|
LUMIERA_THREAD_CLASSES
|
|
/** this just denotes the number of classes listed above,
|
|
it is used to create arrays **/
|
|
LUMIERA_THREADCLASS_COUNT, /* must be <= 256, thats easy or? */
|
|
|
|
// .. various thread flags follow
|
|
/**
|
|
* flag to let the decision to run the function in a thread open to the backend.
|
|
* depending on load it might decide to run it sequentially.
|
|
* This has some constraints:
|
|
* The Thread must be very careful with locking, better don't.
|
|
* @todo explain synchronisation issues
|
|
**/
|
|
LUMIERA_THREAD_OR_NOT = 1<<8,
|
|
|
|
/**
|
|
* Thread must be joined finally
|
|
**/
|
|
LUMIERA_THREAD_JOINABLE = 1<<9
|
|
};
|
|
|
|
#undef LUMIERA_THREAD_CLASS
|
|
|
|
// defined in threads.c
|
|
extern const char* lumiera_threadclass_names[];
|
|
|
|
|
|
// there is some confusion between the meaning of this
|
|
// on one hand it could be used to tell the current state of the thread
|
|
// on the other, it is used to tell the thread which state to enter on next iteration
|
|
#define LUMIERA_THREAD_STATES \
|
|
LUMIERA_THREAD_STATE(ERROR) \
|
|
LUMIERA_THREAD_STATE(IDLE) \
|
|
LUMIERA_THREAD_STATE(RUNNING) \
|
|
LUMIERA_THREAD_STATE(SYNCING) \
|
|
LUMIERA_THREAD_STATE(WAKEUP) \
|
|
LUMIERA_THREAD_STATE(SHUTDOWN) \
|
|
LUMIERA_THREAD_STATE(ZOMBIE) \
|
|
LUMIERA_THREAD_STATE(JOINED) \
|
|
LUMIERA_THREAD_STATE(STARTUP)
|
|
|
|
#define LUMIERA_THREAD_STATE(name) LUMIERA_THREADSTATE_##name,
|
|
|
|
/**
|
|
* Thread state.
|
|
* These are the only states our threads can be in.
|
|
*/
|
|
typedef enum
|
|
{
|
|
LUMIERA_THREAD_STATES
|
|
}
|
|
lumiera_thread_state;
|
|
|
|
#undef LUMIERA_THREAD_STATE
|
|
|
|
// defined in threads.c
|
|
extern const char* lumiera_threadstate_names[];
|
|
|
|
#include "threadpool.h"
|
|
|
|
|
|
|
|
/**
|
|
* The actual thread data
|
|
*/
|
|
struct lumiera_thread_struct
|
|
{
|
|
llist node; // this should be first for easy casting
|
|
|
|
pthread_t id;
|
|
|
|
// TODO: maybe this condition variable should be renamed when we have a better understanding of how it will be used
|
|
lumiera_condition signal; // control signal, state change signal
|
|
|
|
struct timespec deadline;
|
|
|
|
struct nobug_resource_user** rh;
|
|
|
|
// the following member could have been called "class" except that it would conflict with C++ keyword
|
|
// as consequence, it's been decided to leave the type name containing the word "class",
|
|
// while all members/variables called "kind"
|
|
int kind;
|
|
|
|
// this is used both as a command and as a state tracker
|
|
lumiera_thread_state state;
|
|
void (*function)(void *);
|
|
void * arguments;
|
|
};
|
|
|
|
|
|
/**
|
|
* Create a thread structure.
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_new (enum lumiera_thread_class kind,
|
|
const char* purpose,
|
|
struct nobug_flag* flag,
|
|
pthread_attr_t* attrs);
|
|
|
|
/**
|
|
* Destroy and de-initialise a thread structure.
|
|
* Memory is not freed by this function.
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_destroy (LumieraThread self);
|
|
|
|
/**
|
|
* Actually free the memory used by the thread structure.
|
|
* Make sure to destroy the structure first.
|
|
*/
|
|
void
|
|
lumiera_thread_delete (LumieraThread self);
|
|
|
|
/**
|
|
* Start a thread.
|
|
* Threads are implemented as procedures which take a void* and don't return anything.
|
|
* When a thread wants to pass something back to the application it should use the void* it got for
|
|
* constructing the return.
|
|
* * Threads must complete (return from their thread function)
|
|
* * They must not call any exit() function.
|
|
* * Threads can not be cancelled
|
|
* * Threads shall not handle signals (all signals will be disabled for them) unless explicitly acknowledged
|
|
*
|
|
* @param kind class of the thread to start
|
|
* @param function pointer to a function to execute in a thread (returning void, not void* as in pthreads)
|
|
* @param arg generic pointer passed to the thread
|
|
* @param purpose descriptive name of this thread, used by NoBug
|
|
* @param flag NoBug flag used for logging the thread startup and return
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_run (int kind,
|
|
void (*function)(void *),
|
|
void * arg,
|
|
const char* purpose,
|
|
struct nobug_flag* flag);
|
|
|
|
/**
|
|
* Query the LumieraThread handle of the current thread
|
|
*
|
|
*
|
|
* @return pointer to the (opaque) handle of the current lumiera thread or NULL when this is not a lumiera thread
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_self (void);
|
|
|
|
|
|
|
|
/**
|
|
* Set a thread deadline.
|
|
* A thread must finish before its deadline is hit. Otherwise it counts as stalled
|
|
* which is a fatal error which might pull the application down.
|
|
*
|
|
* \par Heartbeat and Deadlines.
|
|
*
|
|
* Any thread can have an optional 'deadline' which must never be hit.
|
|
* This deadlines are lazily checked and if hit this is a fatal error which triggers
|
|
* an emergency shutdown. Thus threads are obliged to set and extend their deadlines
|
|
* accordingly.
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_deadline_set (struct timespec deadline);
|
|
|
|
|
|
/**
|
|
* Extend the deadline of a thread
|
|
* sets the deadline to \c NOW+ms in future. This can be used to implement a heartbeat.
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_deadline_extend (unsigned ms);
|
|
|
|
|
|
/**
|
|
* Clear a thread's deadline
|
|
* Threads without deadline will not be checked against deadlocks (this is the default)
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_deadline_clear (void);
|
|
|
|
|
|
|
|
/**
|
|
* Synchronise with another threads state.
|
|
* This blocks until/unless the other thread reaches a synchronisation point.
|
|
*
|
|
* \par Thread synchronisation
|
|
* The synchronisation primitives act as barrier over 2 threads, any thread reaching
|
|
* a synchronisation point first is blocked until the other one reaches it too.
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_sync_other (LumieraThread other);
|
|
|
|
/**
|
|
* Synchronise current thread
|
|
*
|
|
* this blocks until/unless the other thread reaches a synchronisation point
|
|
* @return on success pointer to self (opaque), or NULL on error
|
|
*/
|
|
LumieraThread
|
|
lumiera_thread_sync (void);
|
|
|
|
// TODO implement timedsync, this is bit tricky because after a timeout, synchronisation points are desynched
|
|
// we possibly need some way to reset/resync this
|
|
//LumieraThread
|
|
//lumiera_thread_timedsync (struct timespec timeout);
|
|
|
|
|
|
/**
|
|
* Joining threads
|
|
* a thread can be set up with the LUMEIRA_THREAD_JOINABLE flag, if so
|
|
* then it must be joined finally. Joining clears the error state of the joined thread
|
|
* and returns it to the joiner.
|
|
*
|
|
*/
|
|
lumiera_err
|
|
lumiera_thread_join (LumieraThread thread);
|
|
|
|
#endif /*BACKEND_THREADS_H*/
|
|
/*
|
|
// Local Variables:
|
|
// mode: C
|
|
// c-file-style: "gnu"
|
|
// indent-tabs-mode: nil
|
|
// End:
|
|
*/
|