[BACK]Return to lockcpu.c CVS log [TXT][DIR] Up to [Development] / performer / src / lib / libpfutil

File: [Development] / performer / src / lib / libpfutil / lockcpu.c (download)

Revision 1.1, Tue Nov 21 21:39:36 2000 UTC (16 years, 10 months ago) by flynnt
Branch: MAIN
CVS Tags: HEAD

Initial check-in based on OpenGL Performer 2.4 tree.
-flynnt

/*
 * Copyright 1993, 1994, 1995, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 *
 * UNPUBLISHED -- Rights reserved under the copyright laws of the United
 * States.   Use of a copyright notice is precautionary only and does not
 * imply publication or disclosure.
 *
 * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to restrictions
 * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
 * in similar or successor clauses in the FAR, or the DOD or NASA FAR
 * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
 * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
 *
 * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
 * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
 * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
 * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
 * GRAPHICS, INC.
 */

/*
 * file: lockcpu.c
 * ----------------
 * 
 * 
 * This file contains routines to lock down processes on processors for 
 *	    app, cull, and draw process.
 *
 * Note: isolating a CPU to specific processors requires root id.
 * 
 *
 * Priority:
 * --------
 *	All processes are 128 or lower so they are not higher priority then kernel
 *	APP  - 120
 *	CULL - 120	
 *	DRAW - 125
 *
 * Policy:
 * -------
 *	CPU0 is never restricted.
 *	APPCULLDRAW - handled by app - takes CPU1.
 *	APP_CULLDRAW - handled by app and draw
 *	APP_CULL_DRAW - each process locks downs its own.
 *
 * Single pipe mappings:
 *  app=APP_CPU, cull=CULL_CPU, draw=DRAW_CPU (defined below)
 *  If there are only 2 CPUs,  app is put on CPU0,  which is not isolated, 
 *	and the draw and cull share CPU1.
 *
 * Multipipe mappings:
 *  If NumCPUs >= 2 + 2*NumPipes then each process can have its own,  with
 *	the application getting CPU1, and UNIX getting CPU0.
 *	The draw will get the next NumPipes cpus, and then the cull
 *	will get the next set.
 *  If  NumCPUs == 1 + 2*NumPipes, then the application shares CPU0 with
 *	UNIX.
 *  Otherwise,  if NumCPUs >= 2 + NumPipes,  then cull and draw processes
 *	for each pipe are paired together.
 *  If their are fewer CPUs then that, then the application is put on
 *	CPU0 with UNIX and we start pairing and once we run 
 *	out, everyone is put on the last CPU.
 *  
 * Routines return 1 if successful,  0 if an error is encountered.
 */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>

/* process control includes */
#include <sys/statfs.h>
#include <sys/types.h>
#include <sys/sysmp.h>
#if defined(__linux__has_schedctl_h__) || !defined(__linux__)
#include <sys/schedctl.h>
#endif  /* __linux__ */

/* IRIS Performer includes */
#include <Performer/pf.h>
#include <Performer/pr.h>
#include <Performer/pfutil.h>

/* default CPUs assignments for locking down processes for 
 * single pipe 4 CPU system
 */
#define APP_CPU 1
#define CULL_CPU 3
#define DRAW_CPU 2
#define LPOINT_CPU 4

#ifdef HAVE_POSIX
#include <sched.h>  /* 6.4+ POSIX Scheduling */
#include <dlfcn.h>
#endif

#define APP_PRIORITY 120
#define CULL_PRIORITY 120
#define DRAW_PRIORITY 125
#define CLOCK_PRIORITY 50
#define ISECT_PRIORITY 75

int pfuLockDownProc(int cpu);
int pfuRunProcOn(int cpu);
int pfuLockDownApp(void);
int pfuLockDownCull(pfPipe *);
int pfuLockDownDraw(pfPipe *);
int pfuLockDownLPoint(pfPipe *);
int pfuRunDiskProcsOn(int cpu);

/* None of these functions are implemented for Linux.
   Will stub them away for now. */
#if !defined(__linux__has_sysmp_h__) && defined(__linux__)
int pfuFreeAllCPUs(void) { STUB; }
int pfuLockDownProc(int cpu) { STUB; }
int pfuRunProcOn(int cpu) { STUB; }
int pfuRunDiskProcsOn(int cpu) { STUB; }
int pfuLockDownApp(void) { STUB; }
int pfuLockDownCull(pfPipe* p) { STUB; }
int pfuLockDownDraw(pfPipe* p) { STUB; }
int pfuLockDownLPoint(pfPipe* p) { STUB; }
#endif

#if !defined(__linux__had_schedctl_h__) && defined(__linux__)
int pfuPrioritizeProcs(int cpu) { STUB; }
#endif

#if !defined(__linux__) || defined(__linux__has_sysmp_h__)
/*
 * FreeAllCPUs (when run as root) will free up all restricted/isolated CPUs
 *  on the system.  This routine should be called before pfConfig() and
 *  just before pfExit();
 */
int
pfuFreeAllCPUs(void)
{
    ptrdiff_t numCPUs = sysmp(MP_NPROCS);
    int i;

    if (numCPUs == sysmp(MP_NAPROCS))
	return TRUE;

    if (!(geteuid() == 0))
    {
	pfNotify(PFNFY_WARN, PFNFY_PRINT, 
		"pfuFreeAllCPUs - Not root - can't free restricted CPUs.");
	return FALSE;
    }
    pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "pfuFreeAllCPUs - Freeing up isolated CPUs.");
    for (i=0; i < numCPUs; i++)
    {
	sysmp(MP_UNISOLATE, i);
	sysmp(MP_EMPOWER, i); /* allow CPU to run any process */
    }
    return TRUE;
}

/*
 * pfuLockDownProc(int cpu) restricts the calling process to the specified cpu
 * and isolates the CPU to running only processes that have locked themselves to
 * this cpu.
 */
int
pfuLockDownProc(int cpu)
{
    ptrdiff_t numCPUs = sysmp(MP_NPROCS);
    long pid = getpid();
    
    if (cpu >= numCPUs)
    {
	pfNotify(PFNFY_WARN, PFNFY_RESOURCE, 
	    "pfuLockDownProc FAILED: CPU %d requested for process %d but I only have %d CPUS!", 
		cpu, pid, numCPUs);
	return 0;
    }
    
    if (sysmp(MP_MUSTRUN, cpu) < 0)
    {
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	    "pfuLockDownProc - MUSTRUN of process %d on CPU %d failed.", pid, cpu);
	return 0;
    } else
	pfNotify(PFNFY_INFO,PFNFY_PRINT,
	    "pfuLockDownProc - Process %d running on CPU %d.", pid, cpu);
	    
    if (sysmp(MP_RESTRICT, cpu) < 0)
    {
	sysmp(MP_RUNANYWHERE, 1);
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		"pfuLockDownProc - RESTRICT of CPU %d for process %d FAILED. "
		"Are you root?", cpu, pid);
	return 0;
    } else {
	sysmp(MP_ISOLATE, cpu);
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	    "pfuLockDownProc - CPU %d is LOCKED running process %d.", cpu, pid);
    }
    return 1;
}

/*
 * pfuRunProcOn(int cpu) restrictes the calling process to running only on the
 * specified CPU but does not isolate the CPU from running any other processes.
 */
int 
pfuRunProcOn(int cpu)
{
    ptrdiff_t numCPUs = sysmp(MP_NPROCS);
    long pid = getpid();
    
    if (cpu >= numCPUs)
    {
	pfNotify(PFNFY_WARN, PFNFY_RESOURCE, 
	    "pfuRunProcOn FAILED: CPU %d requested for process %d but I only have %d CPUS!", 
		cpu, pid, numCPUs);
	return 0;
    }
    
    if (sysmp(MP_MUSTRUN, cpu) < 0)
    {
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	    "pfuRunProcOn() - MUSTRUN of process %d on CPU %d failed.", pid, cpu);
	return 0;
    } else
	pfNotify(PFNFY_INFO,PFNFY_PRINT,
	    "pfuRunProcOn() - Process %d running on CPU %d.", pid, cpu);
    
    return 1;	  
}

/*
 * pfuDiskProcsRunOn will place the all disk reading threads
 * to run on the specified cpu
 * If -1 is passed in, then the disk threads will get their
 * own cpu if available or cpu 0 otherwise.
 */
int
pfuRunDiskProcsOn(int cpu)
{
    int nprocs,i;
    int numPipes = pfGetMultipipe();
    ptrdiff_t numCPUs = sysmp(MP_NPROCS);
    
    if (numCPUs == 1)
    {
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	    "I only have %d processors - "
	    "all disk threads have to run on cpu 0", numCPUs);
	return 0;
    }
   
    if (cpu == -1)
    {
    	if (numCPUs >= 3 + 2 * numPipes)
	    cpu = 2*numPipes+3; /* everyone gets their own = disks go to end */
        else
	    cpu = 0;
    }

#ifndef IRIX5
    nprocs = pfGetNumGlobalQueueServiceProcs();
    for(i=0;i<nprocs;i++)
    	if (sysmp(MP_MUSTRUN_PID, cpu, pfGetGlobalQueueServiceProcPID(i)) < 0)
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	         "MUSTRUN of disk Process %d on cpu %d failed.", pfGetGlobalQueueServiceProcPID(i),cpu);
    	else
	    pfNotify(PFNFY_INFO, PFNFY_PRINT,
	    	"Disk Process %d running on cpu %d.", pfGetGlobalQueueServiceProcPID(i),cpu);
#endif
#if 0
/* XXX - Dont restrict disk read cpu by default */
    if (cpu)
    {
	if (sysmp(MP_RESTRICT, cpu) < 0)
	{
	    sysmp(MP_RUNANYWHERE, 1);
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		    "RESTRICT of cpu %d for disk processes FAILED. "
		    "Are you root?", cpu);
	    return 0;
	} else  {
	    sysmp(MP_ISOLATE, cpu);
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		"Processor %d is LOCKED running disk processes.", cpu);
	}
    } 
#endif

    return 1;
}


/*
 * pfuLockDownApp will place the application processor on processor 0 or 1.
 *  If it is placed on CPU1,  then CPU1 will be isolated.
 *  This routine should be called after pfConfig() and before 
 *  pfConfigPipe or pfFrame().
 */
int
pfuLockDownApp(void)
{
    ptrdiff_t numCPUs = sysmp(MP_NPROCS);
    int numPipes = pfGetMultipipe();
    int cpu = 0;
    
    if (numCPUs == 1)
    {
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	    "I only have %d processors - "
	    "not locking down application process.", numCPUs);
	return 0;
    }
   
    if (numCPUs >= 2 + 2 * numPipes)
	cpu = 1; /* everyone gets their own = application goes on CPU1 */

    if (sysmp(MP_MUSTRUN, cpu) < 0)
    {
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	    "MUSTRUN of app on cpu %d failed.", cpu);
	return 0;
    } else
	pfNotify(PFNFY_INFO, PFNFY_PRINT,
	    "Application process running on cpu %d.", cpu);
    if (cpu)
    {
	if (sysmp(MP_RESTRICT, cpu) < 0)
	{
	    sysmp(MP_RUNANYWHERE, 1);
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		    "RESTRICT of cpu %d for app process FAILED. "
		    "Are you root?", cpu);
	    return 0;
	} else  {
	    sysmp(MP_ISOLATE, cpu);
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		"Processor %d is LOCKED running application process.", cpu);
	}
    } 
    return 1;
}


/* pfuLockDownCull() locks down a cpu for a cull process - requires root id.
 *  This routine should be called from the pfConfigPipeStage cull callback.
 *
 *  If single pipe, uses CPU defined in DRAW_CPU.
 *  If multipipe (and there are enough CPUs),  uses CPU = 2 + 2*pfGetId().
 *  Alternatives tried in order:
 *	1 + 2*pfGetId() -- assumes app is on CPU0
 *	1 + pfGetId() -- will share with draw
 */
int
pfuLockDownCull(pfPipe *p)
{
    ptrdiff_t numCPUs = sysmp(MP_NPROCS);
    long numPipes = pfGetMultipipe();
    long cpu = 0;
    long id;
    
    if (!(pfGetMPBitmask() & PFMP_FORK_CULL))
    {
	pfNotify(PFNFY_NOTICE, PFNFY_PRINT, 
	    "LockDownCull - cull process not forked - handles by app or draw");
	return 0;
    }

    id = pfGetId(p);
    if (numPipes == 1)
    {
	if (numCPUs >= 4)
	    cpu = CULL_CPU;
	else if (numCPUs == 2)
	    cpu = 1;
    } else {
        if (numCPUs >= 2 + 2 * numPipes)
	    cpu = 2 + numPipes + id; /* everyone gets their own! */
	else if (numCPUs >= 1 + numPipes)
	    cpu = 1 + id;  /* unix and app on CPU0, pair up cull and draw */
	else if (id+1 < numCPUs)
	    cpu = id+1; /* unix and app on CPU0 */
	else
	    cpu = numCPUs - 1;
    }
    
    if (cpu)
    {
	pfNotify(PFNFY_NOTICE, PFNFY_PRINT, 
	"Locking down processor %d for the Cull Process.", cpu);
	if (sysmp(MP_MUSTRUN, cpu) < 0)
	{
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		"MUSTRUN of Cull on processor %d failed.", cpu);
	    return 0;
	}
	else if (sysmp(MP_RESTRICT, cpu) < 0)
	{
	    sysmp(MP_RUNANYWHERE, 1);
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		    "ISOLATE of processor %d for Cull process FAILED. "
		    "Are you root?", cpu);
	    return 0;
	} else {
	    sysmp(MP_ISOLATE, cpu);
	}
    } 
    return 1;
}


/* pfuLockDownDraw() locks down a cpu for the draw process 
 *		- requires root id.
 *  This routine should be called from the pfConfigPipeStage callback.
 * 
 *  If single pipe, uses CPU defined in DRAW_CPU.
 *  If multipipe (and there are enough CPUs),  uses CPU 1 + pfGetId().
 */
int
pfuLockDownDraw(pfPipe *p)
{
    ptrdiff_t numCPUs = sysmp(MP_NPROCS);
    long numPipes = pfGetMultipipe();
    long proc = 0;
    long id;
    
    if (numCPUs == 1)
    {
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	"I only have 1 processor - can't Lock Draw down!!!");
	return 0;
    }
    
    id = pfGetId(p);
    if (numPipes == 1)
    {
	if (numCPUs >= 4)
	    proc = DRAW_CPU;
	else if (numCPUs == 2)
	    proc = 1;
    } else {
        if (numCPUs >= 2 + numPipes)
	    proc = 2 + id; /* unix on CPU0, app on CPU1 */
	else if (numCPUs >= 1 + numPipes)
	    proc = 1 + id;  /* unix and app on CPU0 */
	else if (id+1 < numCPUs)
	    proc = id+1; /* unix and app on CPU0 */
	else
	    proc = numCPUs - 1;
    }
    if (proc)
    {
	pfNotify(PFNFY_NOTICE, PFNFY_PRINT, 
	    "Locking  down processor %d for Draw Process of Pipe %d.",
		    proc, id);
	if (sysmp(MP_MUSTRUN, proc) < 0)
	{
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		"MUSTRUN of draw on processor %d failed.", proc);
	    return 0;
	}
	else if (sysmp(MP_RESTRICT, proc) < 0)
	{
	    sysmp(MP_RUNANYWHERE, 1);
		pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
			"RESTRICT of processor %d for draw process FAILED. "
			"Are you root?", proc);
	    return 0;
	} else {
	    sysmp(MP_ISOLATE, proc);
	}
    } 
    return 1;
}


/* pfuLockDownLPoint() locks down a cpu for the Lpoint process 
 *		- requires root id.
 *  This routine should be called from the pfConfigPipeStage callback.
 * 
 *  If single pipe, uses APP CPU if possible
 *  If multipipe (and there are enough CPUs),  uses CPU 1 + pfGetId().
 */
int
pfuLockDownLPoint(pfPipe *p)
{
    ptrdiff_t numCPUs = sysmp(MP_NPROCS);
    long numPipes = pfGetMultipipe();
    long proc = 0;
    long id;
    
    if (numCPUs < 4 )
    {
	pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
	"I only have %d processor - can't Lock LPoint down!!!", numCPUs);
	return 0;
    }
    
    id = pfGetId(p);
    if (numPipes == 1)
    {
	if (numCPUs == 4)
	{
		pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		"Lpoint share the APP cpu because I have only 4 cpus\n");
	    proc = APP_CPU;
	}
	else
	    proc = LPOINT_CPU;
    } else {
        if (numCPUs >= 2 + 2*numPipes)
	    proc = 2 + 2*numPipes + id; /* unix on CPU0, app on CPU1 , Draws on cpu 2,3,4, Cull on cpu 5,6,7
						Lpoint on cpu 8,9,10 */
	else if (numCPUs >= 1 + numPipes)
	    proc = 1 + id;  /* unix and app on CPU0 */
	else if (id+1 < numCPUs)
	    proc = id+1; /* unix and app on CPU0 */
	else
	    proc = numCPUs - 1;
    }
    if (proc)
    {
	pfNotify(PFNFY_NOTICE, PFNFY_PRINT, 
	    "Locking  down processor %d for LPoint Process of Pipe %d.",
		    proc, id);
	if (sysmp(MP_MUSTRUN, proc) < 0)
	{
	    pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
		"MUSTRUN of LPoint on processor %d failed.", proc);
	    return 0;
	}
	else if (sysmp(MP_RESTRICT, proc) < 0)
	{
	    sysmp(MP_RUNANYWHERE, 1);
		pfNotify(PFNFY_NOTICE,PFNFY_PRINT,
			"RESTRICT of processor %d for LPoint process FAILED. "
			"Are you root?", proc);
	    return 0;
	} else {
	    sysmp(MP_ISOLATE, proc);
	}
    } 
    return 1;
}

#if defined(__linux__had_schedctl_h__) || !defined(__linux__)
    /* pri is a bool. TRUE - Then set non-degrading priorities, FALSE - clear priorities */
int
pfuPrioritizeProcs(int pri)
{
    int numPipes = pfGetMultipipe();
    int mpbitmask = pfGetMPBitmask();
    int	i;
    int app;

#ifdef HAVE_POSIX
    void *handle=0;
    int _usePOSIX;	/* Should we use POSIX scheduling */
    struct sched_param schedAttrs;
    
    /* everyone else (libGL.so) explicitly references libc.so.1
     * so we have to do it that way too for the rld refcounting to work.
     */
    _usePOSIX = (pfGetIRIXRelease() >= 6.4);
    if (!_usePOSIX)
    {
	if (!(getenv("_PF_NO_POSIX_SCHED")))
	{
	    handle = dlopen("libc.so.1", RTLD_LAZY);
	    _usePOSIX = (dlsym(handle, "sched_setscheduler") != 0);
	}
    }
#endif
    
    if (pri && geteuid() != 0)
    {
	pfNotify(PFNFY_WARN, PFNFY_USAGE, 
		"pfuPrioritizeProcs() Must be root to increase priorities.");
 	return 0;
    }

#ifdef HAVE_POSIX
    if (!_usePOSIX)
    {
#endif
	app = NDPHIMAX - numPipes + (numPipes * ((mpbitmask & PFMP_FORK_DRAW) != 0));
	if (app > NDPHIMIN)
		app = NDPHIMIN;
	if (pri)
	{
	    if (schedctl(NDPRI, pfGetPID(0, PFPROC_APP), app) < 0)
		pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
		    "pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(0, PFPROC_APP), %d) failed", app);
		    
	    if (schedctl(NDPRI, pfGetPID(0, PFPROC_CLOCK), app+3) < 0)
		pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
		    "pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(0, PFPROC_CLOCK), %d) failed", app+3);
		    
	    if (mpbitmask & PFMP_FORK_ISECT)
	    {
		if (schedctl(NDPRI, pfGetPID(0, PFPROC_ISECT), app+2) < 0)
		    pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
			"pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(0, PFPROC_ISECT), %d) failed", app+2);
	    }
	    if (mpbitmask & PFMP_FORK_COMPUTE)
	    {
		if (schedctl(NDPRI, pfGetPID(0, PFPROC_COMPUTE), app+1) < 0)
		    pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
			"pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(0, PFPROC_COMPUTE), %d) failed", app+1);
	    }
	}
	else
	{
	    if (schedctl(NDPRI, pfGetPID(0, PFPROC_APP), 0) < 0)
		pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
		    "pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(0, PFPROC_APP), 0) failed");
		    
	    if (schedctl(NDPRI, pfGetPID(0, PFPROC_CLOCK), 0) < 0)
		pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
		    "pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(0, PFPROC_CLOCK), 0) failed");
		    
	    if (schedctl(NDPRI, pfGetPID(0, PFPROC_ISECT), 0) < 0)
		pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
		    "pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(0, PFPROC_ISECT), 0) failed");
	}
    
	for (i=0; i<numPipes; i++)
	{
	    if (pri)
	    {
		if (mpbitmask & PFMP_FORK_CULL)
		{
		if (schedctl(NDPRI, pfGetPID(i, PFPROC_CULL), app - i) < 0)
		    pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
			"pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(%d, PFPROC_CULL), %d) failed", i, app-i);
		}
		    
		if (mpbitmask & PFMP_FORK_DRAW)
		{
		if (schedctl(NDPRI, pfGetPID(i, PFPROC_DRAW), app - numPipes - i) < 0)
		    pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
			"pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(%d, PFPROC_DRAW), NDPHIMAX+0) failed", i, 
				app - numPipes - i);
		}
	    }
	    else
	    {
		if (schedctl(NDPRI, pfGetPID(i, PFPROC_CULL), 0) < 0)
		    pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
			"pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(%d, PFPROC_CULL), 0) failed", i);
		    
		if (schedctl(NDPRI, pfGetPID(i, PFPROC_DRAW), 0) < 0)
		    pfNotify(PFNFY_WARN, PFNFY_SYSERR, 
			"pfuPrioritizeProcs() schedctl(NDPRI, pfGetPID(%d, PFPROC_DRAW), 0) failed", i);
	    }
	}
#ifdef HAVE_POSIX

    } else {	    /* (!_usePOSIX) --- ASSERT: We want to use POSIX */
 	if (pri) 
 	{ 
 	    pfNotify(PFNFY_DEBUG, PFNFY_PRINT, "pfuPrioritizeProcs(): Using POSIX"); 
 	     
 	    schedAttrs.sched_priority = APP_PRIORITY; 
 	     
 	    if (sched_setscheduler(pfGetPID(0, PFPROC_APP), SCHED_FIFO, &schedAttrs) < 0) 
 		pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
 		    "pfuPrioritizeProcs() sched_setscheduler(pfGetPID(0, PFPROC_APP), SCHED_FIFO, &schedAttrs) failed"); 
 	     
 	    schedAttrs.sched_priority = CLOCK_PRIORITY; 
 	    	     
 	    if (sched_setscheduler(pfGetPID(0, PFPROC_CLOCK), SCHED_FIFO, &schedAttrs) < 0) 
 		pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
 		    "pfuPrioritizeProcs() sched_setscheduler(pfGetPID(0, PFPROC_CLOCK), SCHED_FIFO, &schedAttrs) failed"); 
 	     
	    if (mpbitmask & PFMP_FORK_ISECT)
	    {
		schedAttrs.sched_priority = APP_PRIORITY - 2; 
		     
		if (sched_setscheduler(pfGetPID(0, PFPROC_ISECT), SCHED_FIFO, &schedAttrs) < 0) 
		    pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
			"sched_setscheduler(pfGetPID(0, PFPROC_ISECT), SCHED_FIFO, &schedAttrs)"); 
	    }
	    if (mpbitmask & PFMP_FORK_COMPUTE)
	    {
		schedAttrs.sched_priority = APP_PRIORITY - 1; 
		     
		if (sched_setscheduler(pfGetPID(0, PFPROC_COMPUTE), SCHED_FIFO, &schedAttrs) < 0) 
		    pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
			"sched_setscheduler(pfGetPID(0, PFPROC_COMPUTE), SCHED_FIFO, &schedAttrs)"); 
	    }
 	} 
 	else 
 	{ 
 	    schedAttrs.sched_priority = 0; 
 	     
 	    if (sched_setscheduler(pfGetPID(0, PFPROC_APP), SCHED_OTHER, &schedAttrs) < 0) 
 		pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
 		    "pfuPrioritizeProcs() sched_setscheduler(pfGetPID(0, PFPROC_APP), SCHED_OTHER, &schedAttrs) failed"); 
 	     
 	    if (sched_setscheduler(pfGetPID(0, PFPROC_CLOCK), SCHED_OTHER, &schedAttrs) < 0) 
 		pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
 		    "pfuPrioritizeProcs() sched_setscheduler(pfGetPID(0, PFPROC_CLOCK), SCHED_OTHER, &schedAttrs) failed"); 
 	     
 	    if (sched_setscheduler(pfGetPID(0, PFPROC_ISECT), SCHED_OTHER, &schedAttrs) < 0) 
 		pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
 		    "sched_setscheduler(pfGetPID(0, PFPROC_ISECT), SCHED_OTHER, &schedAttrs)"); 
 	} 
      
 	for (i=0; i<numPipes; i++) 
 	{ 
 	    if (pri) 
 	    { 
		if (mpbitmask & PFMP_FORK_CULL)
		{
		    schedAttrs.sched_priority = APP_PRIORITY + 1 + i; 
		     
		    if (sched_setscheduler(pfGetPID(i, PFPROC_CULL), SCHED_FIFO, &schedAttrs) < 0) 
			pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
			    "pfuPrioritizeProcs() sched_setscheduler(pfGetPID(i, PFPROC_CULL), SCHED_FIFO, &schedAttrs)", i); 
			 
		}
		if (mpbitmask & PFMP_FORK_DRAW)
		{
		    schedAttrs.sched_priority = APP_PRIORITY + 1 + numPipes + i; 
		     
		    if (sched_setscheduler(pfGetPID(i, PFPROC_DRAW), SCHED_FIFO, &schedAttrs) < 0) 
			pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
			    "pfuPrioritizeProcs() sched_setscheduler(pfGetPID(i, PFPROC_DRAW), SCHED_FIFO, &schedAttrs)", i); 
		}
 	    } 
 	    else 
 	    { 
 		schedAttrs.sched_priority = 0; 
 		 
 		if (sched_setscheduler(pfGetPID(i, PFPROC_CULL), SCHED_OTHER, &schedAttrs) < 0) 
 		    pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
 			"pfuPrioritizeProcs() sched_setscheduler(pfGetPID(i, PFPROC_CULL), SCHED_OTHER, &schedAttrs)", i); 
 		     
 		if (sched_setscheduler(pfGetPID(i, PFPROC_DRAW), SCHED_OTHER, &schedAttrs) < 0) 
 		    pfNotify(PFNFY_WARN, PFNFY_SYSERR,  
 			"pfuPrioritizeProcs() sched_setscheduler(pfGetPID(i, PFPROC_DRAW), SCHED_OTHER, &schedAttrs)", i); 
 	    } 
 	} 
    }
#endif

    return 1;
}
#endif  
#endif