_NTO_TCTL_RUNMASK not working

Hi all,
_NTO_TCTL_RUNMASK flag is not working correctly. As per the QNX explanation, when this flag is used with ThreadCtl, it locks the thread to single CPU. But when i viewed the CPU in which the thread runs (using pidin -F %l command), the thread migrates between different CPU. If i use _NTO_TCTL_RUNMASK_GET_AND_SET flag with ThreadCtl, then only the thread gets locked to single CPU. Could you please explain the reason why _NTO_TCTL_RUNMASK is not working properly.

Regards,
hello

You might want to post your code. Setting the run mask does not automatically force the thread onto one cpu. Setting the run mask with just one bit should.

Probably because you are using it wrong.

Thanks for sending the code.

I haven’t verified this, but I will later today.

Running the program, as you suggest, the processor jumps around. If you add the run-mask to pidin’s output, you will see that it is not set to 1.

If you read the documentation on _NTO_TCL_RUNMASK, it specifically says that threads created do not inherit the run mask you set.

You are using resource manager calls. So I suspect that they are creating threads that do not inherit the run mask.

If you read the doucmention on ThreadCtl() you will see that it is possible to modify the runmask that is inherited.

I substituted the code

unsigned char u8_cpu_run_mask2 =1 ;
ThreadCtl(_NTO_TCTL_RUNMASK, (void *) &u8_cpu_run_mask2);

with this:

#define NUMBER_CPU_NODES 2
#define NODE_MASK 1
struct /* _thread_runmask */
{
int size;
unsigned runmask[RMSK_SIZE(NUMBER_CPU_NODES)];
unsigned inherit_mask[RMSK_SIZE(NUMBER_CPU_NODES)];
} rm;

memset(&rm,0,sizeof(rm));
rm.size = RMSK_SIZE(NUMBER_CPU_NODES];
rm.runmask[0] = NODE_MASK;
rm.inherit_mask[0] = NODE_MASK;

ThreadCtl(_NTO_TCL_RUNMASK_GET_AND_SET_INHERIT,(void *) &rm);

An now my process is stuck on the first cpu.

Thank you maschoen.

So even if we set _NTO_TCTL_RUNMASK, threads created wont lock to a CPU.
In the example attached, ThreadCtl() was called within the main loop itself.
So from my understanding, we need to always use _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT for any threads created by user to be locked to a CPU. Is it correct?

So when do we use _NTO_TCTL_RUNMASK ?

Regards,
hello

Yes, when you want to set the runmask for a thread that will be created. You could set the mask for every thread as it is created if you are creating it. Using the resource manager thread pool library, you are not creating the threads, so you need to use the above call

When you want to change the runmask for a thread.

Hi,

I think the issue is not with using resource manager thread pool library. I have attached another sample code.
Please check it. Here i have tried to lock the main thread and TestThread() thread to CPU 1. But not working.
Please help

[code]#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <sched.h>
#include <time.h>
#include <stdio.h>
#include <sys/siginfo.h>
#include <sys/neutrino.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <sys/neutrino.h>
#include <mqueue.h>
#include <atomic.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <sys/timeb.h>
#include <stdlib.h>

void* TestThread();

int main(int argc, char *argv[])
{
pthread_t thid1;

pthread_create(&thid1, NULL, (void*)&TestThread, NULL);
struct sigevent 	t_timer_event;
struct itimerspec 	t_timer_config;
timer_t				pt_timer_id;
name_attach_t*		pt_evnt_rx_chid = NULL;
struct _pulse		t_pulse_evnt;
int32_t 			s32_timeout_coid = -1;
uint8_t				mask = 1;


ThreadCtl(_NTO_TCTL_RUNMASK, &mask);

pt_evnt_rx_chid = name_attach(NULL, "Test1", 0);
if (NULL == pt_evnt_rx_chid)
{
	printf("Error\n");
}

s32_timeout_coid = name_open("Test1", 0);
if (s32_timeout_coid == -1)
{
	printf("Error\n");
}

SIGEV_PULSE_INIT(
			&t_timer_event,
			s32_timeout_coid,
			10,
			5,
			0 );

if (-1 == timer_create(CLOCK_REALTIME, &t_timer_event, &pt_timer_id))
{
	printf("Error\n");
}

t_timer_config.it_interval.tv_sec = 1;
t_timer_config.it_interval.tv_nsec = 0;
t_timer_config.it_value.tv_sec  = 1;
t_timer_config.it_value.tv_nsec = 0;

timer_settime(pt_timer_id, NULL, &t_timer_config, NULL);

while(1)
{
	if (0 == MsgReceivePulse(pt_evnt_rx_chid->chid, &t_pulse_evnt, sizeof(struct _pulse), NULL))
	{
		if (5 == t_pulse_evnt.code)
		{
			printf("Got pulse, Need to do something here\n");
		}
	}
}
	
pthread_join(thid1, NULL);

}

void* TestThread()
{
struct sigevent t_timer_event;
struct itimerspec t_timer_config;
timer_t pt_timer_id;
name_attach_t* pt_evnt_rx_chid = NULL;
struct _pulse t_pulse_evnt;
int32_t s32_timeout_coid = -1;
uint8_t mask = 1;

ThreadCtl(_NTO_TCTL_RUNMASK, &mask);

pt_evnt_rx_chid = name_attach(NULL, "Test", 0);
if (NULL == pt_evnt_rx_chid)
{
	printf("Error\n");
}

s32_timeout_coid = name_open("Test", 0);
if (s32_timeout_coid == -1)
{
	printf("Error\n");
}

SIGEV_PULSE_INIT(
			&t_timer_event,
			s32_timeout_coid,
			10,
			5,
			0 );

if (-1 == timer_create(CLOCK_REALTIME, &t_timer_event, &pt_timer_id))
{
	printf("Error\n");
}

t_timer_config.it_interval.tv_sec = 1;
t_timer_config.it_interval.tv_nsec = 0;
t_timer_config.it_value.tv_sec  = 1;
t_timer_config.it_value.tv_nsec = 0;

timer_settime(pt_timer_id, NULL, &t_timer_config, NULL);

while(1)
{
	if (0 == MsgReceivePulse(pt_evnt_rx_chid->chid, &t_pulse_evnt, sizeof(struct _pulse), NULL))
	{
		if (5 == t_pulse_evnt.code)
		{
			printf("Got pulse, Need to do something here\n");
		}
	}
}

pthread_exit(NULL);

}
[/code]

Regards,
hello

What do you see happening that’s unexpected?

Thread is not getting locked to single CPU

Take a close look at the type of the variable that has your mask.

I would expect the compiler to generate a warning, no ?

It’s defined as void * so, I wouldn’t expect a warning.

Indeed. And looking at the doc, it’s not obvious that it needs to be an int. I guess when 32 cores will be the norm we will be screwed. I’m using a computer that has 24 so that ain’t too far in the future.

Maybe _NTO_TCTL_RUNMASK will get deprecated in favor of NTO_TCTL_RUNMASK_GET_AND_SET

I tried your runmask code code unsigned char u8_cpu_run_mask2 =1 ; ThreadCtl(_NTO_TCTL_RUNMASK, (void *) &u8_cpu_run_mask2);

when I chek with QNX System profiler I realise that it doesn’t work, and the process migrate