Skip to content

POSIX API

Peter Corke edited this page Sep 4, 2018 · 2 revisions

POSIX threading API

MATLAB function Purpose POSIX reference
argc Get number of command line arguments
argv Get command line argument
stllog Print to log
launch Create a thread pthread_create
cancel Cancel a thread pthread_cancel
join Wait for thread to complete pthread_join
semnew Create semaphore sem_create
sempost Post semaphore sem_post
semwait Wait for semaphore sem_wait
mutex Create a mutex pthread_mutex_create
mutlock Lock a mutex pthread_mutex_lock
mutunlock Unlock a mutex pthread_mutex_unlock
timer Periodically set semaphore timer_create

Each operation is defined by a short file stl/*.m which essentially wraps a function defined by stl.c which is called using coder.ceval.

Threads

Each additional thread must be defined in a separate m-file. This is a limitation of MATLAB Coder – each thread has to be in a separate file (an "entry point function").

If the function returns then the thread is terminated. Typically a thread would be a loop, perhaps even an infinite loop. The loop must contain some blocking operation such as waiting for:

  • a semaphore or mutex
  • a read or write transaction to some device (serial port, I2C etc.)
  • a Linux system call.
This is not a cooperative threading environment, threads that do busy/wait polling will be preempted by the scheduler

When a thread is launched we can pass a uint32 to the thread function. To do this we need to declare a uint32 argument to codegen using

codegen ... thread.m -args uint32(0) ...

Semaphores

Semaphores are used to allow threads to block or enable other threads. For the specific case of protecting a shared resource use a mutex.

id = semaphore(name) returns the id of a new semaphore, initially not raised.

semwait(id) blocks the thread until the semaphore is raised.

semwait(id,true) tests if the semaphore is raised without blocking. If the semaphore is raised it returns true and takes the semaphore, otherwise it returns false.

sempost(id) the semaphore is raised and all threads which are waiting on the semaphore are awakened.

Mutexes

Mutexes are a good tool to protecting a resource shared by multiple threads. Only one thread at a time can lock the mutex.

id = mutex(name) returns the id of a new mutex, initially unlocked.

mutlock(id) blocks the thread until the mutex is unlocked and then this thread locks it.

mutlock(id,true) tests if the mutex can be locked, without blocking. If the mutex is unlocked it returns true and locks the mutex, otherwise it returns false.

mutunlock(id) the mutex is unlocked and it is available for other threads to lock.

Timers

A timer (Linux only) periodically posts a semaphore at a periodic interval. This is useful for periodic tasks where regularity is important (minimize jitter) and where the execution time is variable.

id = timer(name, interval, sem) creates a new timer that fires every interval seconds (a double) and posts the semaphore sem.

This capability is not available for MacOS, see discussion here. A workaround is to use sleep within a thread loop, but this can lead to timing jitter and drift.

STL function summary

The following table lists all STL functions. Where relevant there is a pointer to details of the underlying POSIX function.

Implementation details

Design principles

STL supports a useful subset of POSIX functionality: threads, semaphores and mutexes. Each of these objects is referenced by a small integer handle. The actual POSIX object are kept in arrays within stl.c, the maximum number of threads, semaphores and mutexes (currently 8) can be adjusted by parameters in stl.c.

All objects have string names (MATLAB character arrays) to assist in debugging, these are shown in the log message stream.

When a resource is freed its STL handle is recycled.

Object Handle range Comment
thread 0 main thread
thread 1 → NTHREADS-1 user threads
semaphore 0 → NSEMAPHORES-1
mutex 0 → NMUTEXS-1
timer 0 → NTIMERS-1

An error is thrown if attempting to allocate, at any one time, more objects than the current maximum.

main.c

The C-language main function is provided by stl/main.c which performs some initialization and then calls user.m.

Command line arguments

% ./user bob alice 123.5

Command line arguments are not passed through to user but are kept by STL and made available via functions.

argc returns the number of arguments, always one or more. In the example above it will return 4.

argv(i) returns the i'th argument as a string. i=0 gives the name of the command, and the maximum value of i is one less than the value returned by argc. In the example above argv(0) = './user' which is the command used to invoke the program, and argv(3) = '123.5'.

Debugging

Detailed logging of all events to the log channel can be enabled.

stldebug(true)

Events include object creation, thread launch and exit, semaphore post and wait, mutex lock and unlock. Each entry lists the date and time (to μs precision) and the name of the thread that was executing.

An example log file enabled by debugging is:

2018-08-27 09:25:02.480656 [thread2] hello from thread2, id #2
2018-08-27 09:25:03.479300 [user] cancelling thread #2 <thread2>
2018-08-27 09:25:03.479371 [user] waiting for thread #2 <thread2>
2018-08-27 09:25:03.479435 [user] thread complete #2 <thread2>
2018-08-27 09:25:05.479844 [user] creating semaphore #0 <sem1>
2018-08-27 09:25:05.479977 [user] sem id 0
2018-08-27 09:25:06.481025 [user] thread id 1
2018-08-27 09:25:06.481079 [thread3] starting posix thread <thread3> (0xA162220)
2018-08-27 09:25:06.481109 [thread3] waiting for semaphore #0 <sem1>
Clone this wiki locally