Thread synchronization: mutex

How does mutex work?
  • Only one thread may have the mutex locked at any given time.
  • Threads blocks if the mutex is already owned by another thread.
  • When the mutex is unlocked, the highest-priority thread will unblock and become the new owner of the mutex.
Note: in QNX, On most processors, acquiring a free/unlocked mutex doesn’t require entry to the kernel — the OS/kernel is only used to resolve contention. Therefore, acquisition and rlease of an uncontested critical section or resouce is very quick. The kernel is only involved:
  • to put the waiting thread to a blocked list if the mutex is being held, and
  • to unblock a thread if it is of the highest priority thread in the waiting list, when the mutex is being released.
(default) mutex attributes
  • PTHREAD_PRIO_INHERIT  The priority of the thread, which has locked the mutex, is raised to the highest priority of the threads, which are blocked, waiting on this mutex.
  • PTHREAD_RECURSIVE_DISABLE   any thread that tries to lock an already locked mutex becomes blocked.
Mutex administration
  •  initialize a statically allocated mutex, with the default attributes
    • pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
  • a normal initialization/destroy of mutex
    •  int pthread_mutex_init(&mutex, &attr); // if attr is NULL, default attributes.
    •  int pthread_mutex_destroy(&mutex)
  • play attribute values
    • pthread_mutexattr_get/set…(&attr, xx);
Using muex
  • Int pthread_mutex_lock(&mutex)  // the thread blocks until it has accquired the mutex.
  • pthread_mutex_timedlock(&mutex, struct timespec *ts_timeout);
  • pthread_mutex_timelock_monotonic(&mutex, struct timespec *ts_timeout)); // not affected by changes to the system time.
  • Int pthread_mutex_unlock(&mutex);
  • Int pthread_mutex_trylock(&mutex); // not block the thread if the mutex is already locked. The return value “EBUSY” means the mutex is already locked.

Thread creation/termination

Thread Creation

int pthread_create(&tid, &attr, func, &arg);
Thread destroy
  1. in a different thread
    • int pthread_cancel( tid );  // tid can be pthread_self()
      • the cancellation type and state of the target thread determine when the cancellation takes effect.
    • int pthread_join(tid, **value_ptr);
    • int pthread_abort(tid);  // tid can be pthread_self()
      • termination takes effect immediately (don’t wait for a cancellation point).
      • no cancellation handler called.
      • resources are not released (mutexes, file descriptors, etc)
  2. in the thread itself
    • void pthread_exit(*value_ptr);
      • value_ptr: thread’s exit status, which carries whatever you want the other thread (e.g. the thread calls pthread_join()) to know.
      • when the thread start routine returns, pthread_exit() is called implicitly.
    • void pthread_cleanup_push(cleanup_handler, &arg)
    • void pthread_cleanup_pop(execute)  // execute = 0, means the handler will not be executed.
      • the cleanup handler is pop/executed when the thread:
        • exits
        • acts on a cancellation request.
        • calls pthread_cleanup_pop() with nonzero.
      • NOTE! the cleanup handler should support multiple entrances.
#include <pthread.h>
struct my_context;
void *my_thread1(void *arg)
    struct my_context *cx=(struct my_context *)arg;
    return NULL; // pthread_exit() is called implicitly
void my_cleanup(void *args)
    struct my_context *ctx = (struct my_context *)args;
    if(ctx->iid != -1) {
void *my_thread2(void *arg)
    struct my_context *cx=(struct my_context *)arg;
    ctx->iid = InterruptAttachEvent(…);
    pthread_cleanup_push(my_cleanup, ctx);
    return NULL;
int main(int argc, char **argv)
    struct my_context *ctx;
    // create a thread with default attributes.  Don’t care about thread ID.
    // pthread_create(NULL, NULL, my_thread1, ctx);
    // create a thread with priority set to +20
    pthread_t tid;
    pthread_attr_t attr;
    struct sched_param param;
    int allowable_prio;
    pthread_getschedparam(pthread_self(), NULL, &param);
    allowable_prio = sched_get_priority_adjust(-1, SCHED_NOCHANGE, +20);
    param.sched_priority = allowable_prio;
    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    // pthread_attr_setschedpolicy(&attr, policy);  is this required?
    pthread_attr_setschedparam(&attr, &param);
    pthread_create(&tid, &attr, my_thread1, ctx); // all pointers
pthread_join(tid, NULL);  // wait/block until the target thread(tid) has terminated.

Thread atributes

 Process and thread: processes own resources, threads run code.
(Default) thread attributes
  • PTHREAD_CREATE_JOINABLE: the thread is put into a zoombie state when it terminates, until you retrieve its exit status or detach it.
  • inherit-scheduling attribute
    • PTHREAD_INHERIT_SCHED: the thread inherits the scheduling policy of its parent thread.
    • another value: PTHREAD_EXPLICIT_SCHED
      • if we want to use different scheduling parameters for the new thread, this need to be changed to PTHREAD_EXPLICIT_SCHED.
  • cancellation state
    • PTHREAD_CANCEL_ENABLE: cancellation requests may be acted on accordingly to the cancelation type
    • another state: PTHREAD_CANCEL_DISABLE
  • cancellation type
    • PTHREAD_CANCEL_DEFERRED: cancellation requests are held pending until a cancellation point.
  • 4K stack

Thread scheduling

  1. Scheduling policy: inherited from the parent process (PTHREAD_INHERT_SCHED), by default. In all cases, a higher-priority thread can preempts all lower-priority threads one it gets READY.
    • FIFO scheduling: apply only when two or more threads that share the same priority are READY.
    • Round-robin scheduling: a thread stop executing when it consumes its timeslice.
    • Sporadic scheduling
  2. Scheduling priority, independent of the scheduling policy. The scheduler selects the highest priority thread to run, from the READY threads.
    • range 0 ~ 255
      • 0 is for the special idle thread (in kernel), which is always ready to run.
      • 1 ~ 63 for user threads. (the range can be changed by pronto -P option).
      • 1 ~255 for root threads.

Data structure

  • pthread_attr_t: stack size, detachstate, schedparam, schedpolicy, etc
  • struct sched_param: contains sched_priority, sched_curpriority
  • int policy: FIFO(1), RR(2, default?), OTHER(3), SPORADIC(4)


  1. process level
    • Get/set the priority of a process; if pid 0 used, it is for current process.
      • sched_setparam(pid|0, &sched_param): 
      • sched_getparam(pid|0, &sched_param);
    • get the priority range for the scheduling policy
      • sched_get_priority_max(int policy);
      • sched_get_priority_min(int policy);
    • calculate the allowable priority for the policy
      • allowable_priority = sched_get_priority_adjust(int priority, int policy, int adjust);
        • priority = -1, priority of current thread.
        • policy=SCHED_NOCHANGE, the policy of the called thread
        • adjust=+20, we want a priority of “priority + 20”.
  2. thread level (used after the thread is created)
    • Set/get scheduling parameters
      • pthread_getschedparam(tid, &policy, &param);
      • pthread_setschedparam(tid, policy, &param)
    • set the priority
      • pthread_setschedprio(tid, prio);
      • Note: the priority get should be achieved using pthread_getschedparam().
    • set cancellation state/type
      • pthread_setcancelstate(int newstate, &oldstate)
      • pthread_setcanceltype(int newtype, &oldtype);
        • not _get functions.
        • can only be set after thread creation.
  3. attribute level (only take effect before the thread is created)
    • initialize/destroy attr object
      • pthread_attr_init(&attr)
      • pthread_attr_destroy(&attr);  // the memory is not freed. but after destroying, reinit the object using pthread_attr_init()
    • set/get policy
      • pthread_attr_setschedpolicy(&attr, int policy)
      • pthread_attr_getschedpolicy(&attr, &policy)
    • set/get scheduling parameters
      • pthread_attr_setschedparam(&attr, &param);
        • used only after pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
      • pthread_attr_getschedparam(&attr, &param);
    • set/get inherit-scheduling attributes
      • pthread_attr_setinheritsched(&attr, interitsched);
      • pthread_attr_getinheritsched(&attr, &interitsched);
        • need to be set prior to the thread creation

Video decoder basics

  1. AFE (analog Front End): pre-process and digitizes the analog signal.
  2. Automatic gain control (via a variable gain amplifier) on Luma or Chroma
    1. For luma, AGC may operate based on the depth of the horizontal sync pulse, or a fixed manual gain, etc.
    2. For chroma, AGC may operate based on the depth of the horiontal sync pulse on the luma channel, etc
  3. Color killer: usually there is a threshold, if the color carrier of the incoming video signal is less than the threshold,  the decoder switchs off the color processing.
  4. Clamping circuit: restore the proper DC level.
  5. Video characteristic adjustement
    1. Brightness
    2. Contrast
    3. Color saturation
    4. Hue
    5. Sharpness
    6. CTI (color transient improvement): to enhance the color bandwidth

color parameters

Brightness  -128 ~ 127, usually set in the register as (8-bit) 2’s complement form.  1(1), 0x7F(127) is the brightest. 0x80(-128) is the darkest, 0xFF (-1).
Contrast (luminance contrast gain)  -128 ~ 127, 100(64h) means a gain of 1. Increase of contrast by “1” means adjustment of gain by %1.
Saturation(chroma gain, for U and V)  -128 ~ 127
Hue  +36 to –36. Only effective on NTSC system. The positive value gives greenish tone and negative value gives purplish tone.
Sharpness (for luma)  0 ~ 15. 15 provide the strongest sharpness.