Priority Questions

Hello,

I do a little test with QNX 6.2.1 and I 'm confusing with the result :question: .
I use example source code from name_attach library manual.
a client “C” sends 5 messages to a server “S” which replies immediately. for the test a make a long loop before to reply and can use pidin 8) .

Now suppose we have
S a server process running at priority level 6
C1 a first client running at priority level 7
C2 a second client running at priority level 8.

I start C1 which send it’s first message to S: S see it’s priority rises to 7 ( ok ) C1 is reply blocked
I start C2 which send it’s first message to S: S see it’s priority rises to 8 ( ok priority inversion avoidance) C2 is send blocked.
when S replies to C1 , C2 take the cpu and sends all its messages. S stays at level 8 (ok )
Now C2 exits after sending all messages.
C1 resume sending to S but S STAYS at level 8 for a certain time before to decrease to level 7. And if I start an other process “X” at level 8 X and S sharing the level 8 for this time :open_mouth:

I don’t know if I was very clear ? :laughing:
Any Ideas ?

what is the time that S stays at 8 after C2 exits?

a short time, about 2 or 3 seconds

Wanna post your code somewhere?

Hello,

the code I use is the code released by QNX with the library 's example about name_attach. I just broke the code into 2 parts ( server / client ).
I add a loop in the server before reply to do the test more comfortably.

The two clients c1 and c2 are running the same code ( I have just added process identification in the message )

The process called X do an simple infinite loop to use 100 % of cpu.

Philippe.

When S is at 8 (before it get back to 7), what is the status showed
by pidin of (C1 and S)?

Does C1 “REPLY” ? Does S “RUNNING” or “RECEIVE” ?

S = _serv, C1 = _c1 , C2 = _c2, X = _goi

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY
64360487 1 ./_c2 8o REPLY 50122789

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY
64360487 1 ./_c2 8o REPLY 50122789

==> Now C2 ( prio 8 ) disappears and S stays at prio 8

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY

Now a new process at a real prio 8 appears ( _goi ) what does QNX ? round robin on between a process at real prio 8 and the server at false prio 8 but real prio 7 ? :open_mouth:

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY
65224752 1 ./_goi 8o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY
65212455 1 ./_goi 8o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY
65212455 1 ./_goi 8o READY

neutrino$pidin | grep _
50122789 1 ./_serv 8o READY
64352294 1 ./_c1 7o READY
65212455 1 ./_goi 8o READY

==> Ok QNX decrease _serv priority

neutrino$pidin | grep _
50122789 1 ./_serv 7o READY
64352294 1 ./_c1 7o REPLY 50122789
65212455 1 ./_goi 8o READY

neutrino$pidin | grep _
50122789 1 ./_serv 7o READY
64352294 1 ./_c1 7o REPLY 50122789
65212455 1 ./_goi 8o READY

Sorry for this complicated post :wink:
Philippe

c1 keeps on “READY”, sounds like he isn’t get a chance to finish its MsgSend().
and I wonder what is the server doing in READY but not RECEIVE ?

Certainly if you have a process X which runs ready (using 100% of CPU) at priority 8, nothing will ever run at a lower priority. The thing to remember when using pidin is it is a snapshot and just because a process is READY, that does not imply that it will ever get to run.

You said you added code to loop. How are you delaying? Just doing a busy loop is not the way to do it. Add a sleep(20) to sleep instead of busy looping and see what that does.

Also, although you may want to be brief, it is hard to get a real idea of what is going on without the source (as cdm asked) or at least one complete pidin listing.

:arrow_right: the server code:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <iostream.h>
#include <unistd.h>
#include <time.h>
#include <inttypes.h>
#include <pthread.h>

#include <sched.h>

#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <sys/mman.h>
#include <sys/syspage.h>

#include <hw/inout.h>

void Tempo( int v )
{
while( v ) {
for( int ii = 0; ii < 1000000 ; ii++ );
v–;
}
}

#define ATTACH_POINT “myname”

/* We specify the header as being at least a pulse */
typedef struct _pulse msg_header_t;

/* Our real data comes after the header */
typedef struct _my_data {
msg_header_t hdr;
int data;
} my_data_t;

/*** Server Side of the code ***/
int main() {
name_attach_t *attach;
my_data_t msg;
int rcvid;

/* Create a local name (/dev/name/local/...) */
if ((attach = name_attach(NULL, ATTACH_POINT, 0)) == NULL) {
    return EXIT_FAILURE;
}

/* Do your MsgReceive's here now with the chid */
while (1) {
    rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL);

    if (rcvid == -1) {/* Error condition, exit */
        break;
    }

    if (rcvid == 0) {/* Pulse received */
        switch (msg.hdr.code) {
        case _PULSE_CODE_DISCONNECT:
            /*
             * A client disconnected all its connections (called
             * name_close() for each name_open() of our name) or
             * terminated
             */
            ConnectDetach(msg.hdr.scoid);
            break;
        case _PULSE_CODE_UNBLOCK:
            /*
             * REPLY blocked client wants to unblock (was hit by
             * a signal or timed out).  It's up to you if you
             * reply now or later.
             */
            break;
        default:
            /*
             * A pulse sent by one of your processes or a
             * _PULSE_CODE_COIDDEATH or _PULSE_CODE_THREADDEATH 
             * from the kernel?
             */
        continue;
        }
    }

    /* A QNX IO message received, reject */
    if (msg.hdr.type >= _IO_BASE && msg.hdr.type <= _IO_MAX) {
        MsgError(rcvid, ENOSYS);
        continue;
    }

    /* A message (presumable ours) received, handle */
    printf("Server receive %d \n", msg.data);
    Tempo(5000);
    MsgReply(rcvid, EOK, 0, 0);

}

/* Remove the name from the space */
name_detach(attach, 0);

return EXIT_SUCCESS;

}

:arrow_right: C1 code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <iostream.h>
#include <unistd.h>
#include <time.h>
#include <inttypes.h>
#include <pthread.h>

#include <sched.h>

#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <sys/mman.h>
#include <sys/syspage.h>

#include <hw/inout.h>

#define ATTACH_POINT “myname”

/* We specify the header as being at least a pulse */
typedef struct _pulse msg_header_t;

/* Our real data comes after the header */
typedef struct _my_data {
msg_header_t hdr;
int data;
} my_data_t;

int main () {
my_data_t msg;
int fd;

if ((fd = name_open(ATTACH_POINT, 0)) == -1) {
    return EXIT_FAILURE;
}

/* We would have pre-defined data to stuff here */
msg.hdr.type = 0x00;
msg.hdr.subtype = 0x00;

/* Do whatever work you wanted with server connection */
  for (int ii = 0; ii < 5 ; ii++ ) {
    msg.data = 0x100 | ii;
    printf("Client 1 sending %d \n", msg.data);
    if (MsgSend(fd, &msg, sizeof(msg), NULL, 0) == -1) {
        break;
    }
}

/* Close the connection */
name_close(fd);
return EXIT_SUCCESS;

}

:arrow_right: C2 code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <iostream.h>
#include <unistd.h>
#include <time.h>
#include <inttypes.h>
#include <pthread.h>

#include <sched.h>

#include <sys/dispatch.h>
#include <sys/neutrino.h>
#include <sys/mman.h>
#include <sys/syspage.h>

#include <hw/inout.h>

#define ATTACH_POINT “myname”

/* We specify the header as being at least a pulse */
typedef struct _pulse msg_header_t;

/* Our real data comes after the header */
typedef struct _my_data {
msg_header_t hdr;
int data;
} my_data_t;

int main () {
my_data_t msg;
int fd;

if ((fd = name_open(ATTACH_POINT, 0)) == -1) {
    return EXIT_FAILURE;
}

/* We would have pre-defined data to stuff here */
msg.hdr.type = 0x00;
msg.hdr.subtype = 0x00;

/* Do whatever work you wanted with server connection */
 for (int ii = 0; ii < 5 ; ii++ ) {
    msg.data = 0x200 | ii;
    printf("Client 2 sending %d \n", msg.data);
    if (MsgSend(fd, &msg, sizeof(msg), NULL, 0) == -1) {
        break;
    }
}

/* Close the connection */
name_close(fd);
return EXIT_SUCCESS;

}

:arrow_right: X code :
#include <stdio.h>
int main( )
{
char Texte[80];
while(1) { printf( “Running in priority \n”); }
}

I thing if I replace the printf by a delay call in the code of X, I change the problem because the X process goes to nanosleep state and yield the CPU and that is not that I want. I want the X process runs with highest priority than the server S.