[Previous] [Contents] [Index] [Next]

Caution: This version of this document is no longer maintained. For the latest documentation, see http://www.qnx.com/developers/docs.

ThreadCtl(), ThreadCtl_r()

Control a thread

Synopsis:

#include <sys/neutrino.h>

int ThreadCtl( int cmd, 
               void * data );

int ThreadCtl_r( int cmd, 
                 void * data );

Arguments:

cmd
The command you want to execute; see below.
data
A pointer to data associated with the specific command; see below.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

These kernel calls allow you to make QNX-specific changes to a thread.

The ThreadCtl() and ThreadCtl_r() functions are identical except in the way they indicate errors. See the Returns section for details.

The following calls are defined:

ThreadCtl(_NTO_TCTL_ALIGN_FAULT, data)
Control the misaligned access response. The data argument is a pointer to an int whose value indicates how you want to respond:

The function sets data to a positive or negative number, indicating the previous state of the the alignment-fault handling.

ThreadCtl(_NTO_TCTL_NAME, struct _thread_name name)
Set and retrieve the name of the current thread. The data structure contains the following fields:
new_name_len
name_buf_len
name_buf[1]

The name_buf is a continuous buffer that extends the structure that contains space for max(name_buf_len, new_name_len). If new_name_len is

The current thread name (or previous name if a new name is being set) is placed as a NULL-terminated string in the buffer pointed to by name_buf. The name returned has a maximum of name_buf_len bytes. No thread name is returned if name_buf_len is zero.


Note:
  • Currently, the thread names are limited to _NTO_THREAD_NAME_MAX.
  • You can also use the pthread_getname_np() and pthread_getname_np() functions instead of calling ThreadCtl() directly.

This call was defined in the QNX Neutrino Core OS 6.3.2.


ThreadCtl(_NTO_TCTL_IO, 0)
Request I/O privileges; let the thread execute the I/O opcodes in, ins, out, outs, cli, sti on architectures where it has the appropriate privilege, and let it attach IRQ handlers. You need root permissions to use this command. If a thread attempts to use these opcodes without successfully executing this call, the thread faults with a SIGSEGV when the opcode is attempted.
Note: Threads created by the calling thread inherit the _NTO_TCTL_IO status.

ThreadCtl(_NTO_TCTL_ONE_THREAD_HOLD, (void *) tid)
Hold one thread, with tid as thread ID, in the process. Returns an error ESRCH when tid is not the existing thread.
Note: This call was defined in the QNX Neutrino Core OS 6.3.2.

ThreadCtl(_NTO_TCTL_ONE_THREAD_CONT, (void *) tid)
Continue one thread, with tid as thread ID, in the process. Returns an error ESRCH when tid is not the existing thread.
Note: This call was defined in the QNX Neutrino Core OS 6.3.2.

ThreadCtl(_NTO_TCTL_RUNMASK, (int)runmask)
Set processor affinity for the calling thread in a multiprocessor system. Each set bit in runmask represents a processor that the thread can run on.

By default, a thread's runmask is set to all ones, which allows it to run on any available processor. A value of 0x01 would, for example, force the thread to only run on the first processor.

You can use _NTO_TCTL_RUNMASK to optimize the runtime performance of your system by, for example, relegating nonrealtime threads to a specific processor. In general, this shouldn't be necessary, since the QNX realtime scheduler always preempts a lower-priority thread immediately when a higher priority thread becomes ready.

The main effect of processor locking is the effectiveness of the CPU cache, since threads can be prevented from migrating.


Note: Threads created by the calling thread don't inherit the specified runmask.

ThreadCtl(_NTO_TCTL_RUNMASK_GET_AND_SET, (int *) data)
Get and set the runmask (the processor affinity) to a proper value for the calling thread in a multiprocessor system. The data parameter is a pointer to an integer. On input, the pointer to value is used to set the new runmask for the thread (see _NTO_TCTL_SET_RUNMASK for details.) After the function has completed, the contents of *data will be replaced with the previous runmask for the thread. Calling ThreadCtl again with the same pointer will restore the runmask to the state before the call.
ThreadCtl(_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT, &(struct _thread_runmask *) data)
Manipulate calling thread's runmask and inherit mask. This call takes a pointer to a struct _thread_runmask. The values for both masks at the time of the call are returned in their respective members of the passed in struct. If the masks are passed as zero at the time of the call, the masks are left unaltered, otherwise they are set to the specified value(s). See example below.
Note: This call was defined in the QNX Neutrino Core OS 6.3.2.

ThreadCtl(_NTO_TCTL_THREADS_CONT, 0)
Unfreeze all threads in the current process that were frozen using the _NTO_TCTL_THREADS_HOLD command.
ThreadCtl(_NTO_TCTL_THREADS_HOLD, 0)
Freeze all threads in the current process except the calling thread.
Note: Threads created by the calling thread aren't frozen.

Blocking states

These calls don't block.

Returns:

The only difference between these functions is the way they indicate errors:

ThreadCtl()
If an error occurs, the function returns -1 and sets errno. Any other value returned indicates success.
ThreadCtl_r()
EOK is returned on success. This function does NOT set errno. If an error occurs, any value in the Errors section may be returned.

Errors:

E2BIG
The name is larger than the accepted size.
EINVAL
The name buffer length is invalid or smaller that the new name length.
EPERM
The process doesn't have superuser capabilities.
ESRCH
The tid is not the existing thread.

Examples:

#include <sys/neutrino.h>
#include <sys/syspage.h>
#include <malloc.h>
#include <stdio.h>

int
main(void)
{
   int *rsizep, rsize, size_tot;
   unsigned *rmaskp, *inheritp;
   unsigned buf[8];
   void *freep;

   /*
    * struct _thread_runmask is not
    * uniquely sized so we construct
    * our own.
    */
   
   rsize = RMSK_SIZE(_syspage_ptr->num_cpu);

   size_tot = sizeof(*rsizep);
   size_tot += sizeof(*rmaskp) * rsize;
   size_tot += sizeof(*inheritp) * rsize;

   if (size_tot <= sizeof(buf)) {
      rsizep = buf;
      freep = NULL;
   }
   else if ((rsizep = freep = malloc(size_tot)) == NULL) {
      perror("malloc");
      return 1;
   }

   memset(rsizep, 0x00, size_tot);

   *rsizep = rsize;
   rmaskp = (unsigned *)(rsizep + 1);
   inheritp = rmaskp + rsize;

   /*
    * Both masks set to 0 means get current
    * values without alteration.
    */

   if (ThreadCtl(_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT, rsizep) == -1) {
      perror("_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT");
      free(freep);
      return 1;
   }

   /*
    * Restrict our inherit mask to the last cpu, leave
    * runmask unaltered.
    */
   
   memset(rsizep, 0x00, size_tot);
   *rsizep = rsize;
   RMSK_SET(_syspage_ptr->num_cpu - 1, inheritp);

   if (ThreadCtl(_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT, rsizep) == -1) {
      perror("_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT");
      free(freep);
      return 1;
   }

   free(freep);
   return 0;
}

Classification:

QNX Neutrino

Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes

See also:

InterruptDisable(), InterruptEnable(), InterruptMask(), InterruptUnmask()


[Previous] [Contents] [Index] [Next]