HPlogo STREAMS/UX for the HP 9000 Reference Manual > Chapter 4 STREAMS/UX Multiprocessor Support

Running Modules and Drivers in Uniprocessor Emulation Mode

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

STREAMS/UX supports uniprocessor emulation for modules and drivers. Modules and drivers which run on uniprocessor systems can run on multiprocessor systems under UP emulation without code changes. This section presents an overview of UP emulation, describes how to configure modules and drivers for UP emulation, describes what happens when a stream contains both UP emulation and MP scalable modules, and describes how UP emulation affects performance. Lastly, this section contains some UP emulation programming guidelines.

How STREAMS/UX Executes UP Emulation Modules and Drivers

This section describes how STREAMS/UX supports UP emulation. HP-UX provides UP emulation for non-STREAMS device drivers which were developed for uniprocessor systems.

HP-UX uses a semaphore called the I/O semaphore and a spinlock known as the spl lock to implement UP emulation. HP-UX uses the I/O semaphore to serialize driver system calls. HP-UX acquires the I/O semaphore before calling the driver to process a system call. HP-UX uses the spl lock to prevent a driver interrupt on one processor from running in parallel with a driver system call on another processor. When a driver calls spln to raise the spl level, HP-UX acquires the spl lock. When an interrupt occurs for a UP emulation driver, HP-UX acquires the spl lock before calling the driver's interrupt handler.

STREAMS/UX extends UP emulation for STREAMS/UX modules and drivers. A stream can be entered in two ways. One way is through a system call. Either the I/O system or STREAMS/UX acquires the I/O semaphore before executing a system call for a UP emulation stream. Also, a stream can be entered from non-STREAMS software in the kernel. For example, an interrupt handler can call putq, putnext,put, or streams_put to enter a stream.

If code on the interrupt control stack (ICS) calls putq for a UP emulation stream, the STREAMS/UX UP emulation scheduler runs the service routine. This scheduler acquires the I/O semaphore. If an interrupt occurs for a UP emulation driver, the I/O system acquires the spl lock. Then if the interrupt handler calls put, putnext, or streams_put, STREAMS/UX usually executes the put routine on the ICS with the spl lock. Note that the STREAMS/UX utilities do not acquire the spl lock. An MP scalable interrupt handler may not be able to safely call put, putnext, or streams_put to enter a UP emulation stream.

STREAMS/UX protects the various callback functions in different ways. STREAMS/UX does not have to acquire the I/O semaphore or spl lock to run esballoc free routines in UP emulation mode. The free routine will automatically run in the same mode as the module which calls freeb. Also, the HP-UX I/O system protects timeout callback routines by obtaining the spl lock before running the routine.

bufcall and weld callback functions are always run under UP emulation. The STREAMS/UX memory and weld daemons always obtain the I/O semaphore before running UP emulation or MP scalable callback routines. This should not hurt the performance of MP scalable modules because weldq and bufcall are not called very often.

Configuring Modules and Drivers for UP Emulation

Modules and drivers run in UP emulation mode by default. To configure a module or driver to run in UP emulation mode, do not specify any MP flags. The examples below show how to configure UP emulation modules and drivers by creating a master file $DEVICE table entry or a module or driver install function. See Chapter 5 for more information about configuring modules and drivers.

MASTER FILE $DEVICE TABLE CONFIGURATION

name handle type mask block char

lo loinfo 21 FC -1 75 /*0x10000 not set in mask */
lmodb lmbinfo 40 0 -1 -1 /*0x10000 not set in mask */

INSTALL FUNCTION CONFIGURATION

LO DRIVER

static drv_info_t lo_drv_info = { /* driver information */
"lo", /* name */
"pseudo", /* class */
DRV_CHAR | DRV_PSEUDO, /*NOTE* DRV_MP_SAFE flag not specified */
-1, /* block major number */
75, /* character major number */
NULL, NULL, NULL, /* cdio, gio_private, and cdio_private structures */
}

static drv_ops_t lo_drv_ops = { /* driver entry points */
NULL, /* open */
NULL, /* close */
NULL, /* strategy */
NULL, /* dump */
NULL, /* psize */
NULL, /* mount */
NULL, /* read */
NULL, /* write */
NULL, /* ioctl */
NULL, /* select */
NULL, /* option1 */
NULL, NULL, NULL, NULL, /* reserved entry points */
0, /* device flags */
}

static streams_info_t lo_str_info = {   /* streams information */
"lo", /* name */
75, /* major number */
{&lorinit, &lowinit, NULL, NULL},/* streamtab */
STR_IS_DEVICE, /*NOTE* MGR_IS_MP flag not specified */
0, /* synchronization level */
"", /* elsewhere sync name */
}
int
lo_install()
{
int retval;

if ((retval = install_driver(&lo_drv_info, &lo_drv_ops)) != 0)
return(retval);

if ((retval = str_install(&lo_str_info)) != 0) {
uninstall_driver(&lo_drv_info);
return(retval);
}

/* success */
return 0;

}

LMODB MODULE

static streams_info_t lmodb_str_info = { /* streams information */
"lmodb", /* name */
-1, /* major number */
{ &lmodbrinit, &lmodbwinit }, /* streamtab */
STR_IS_MODULE, /* *****NOTE***** MGR_IS_MP flag not
specified */
0, /* synchronization level */
"", /* elsewhere sync name */
}

int
lmodb_install()
{
int retval;

return(str_install(&lmodb_str_info));

}

Mixing MP Scalable and UP Emulation Modules and Drivers

Because UP emulation and MP scalability are configured separately for each module or driver, it is possible for a stream to contain both UP emulation and MP scalable modules and drivers. If any module or driver in a stream needs to run in UP emulation mode, STREAMS/UX runs the entire stream under UP emulation.

When a module is pushed onto a stream, STREAMS/UX checks if either the module is configured for UP emulation or if the stream is running under UP emulation. If either condition is true, the module and the entire stream run under UP emulation. Also, when the module is popped, the stream does not change back to its original mode.

When a driver is linked under a multiplexor, STREAMS/UX checks if both streams run in the same mode. If they do not, STREAMS/UX changes the MP scalable stream to run in UP emulation mode. When the driver is unlinked, STREAMS/UX does not change a stream back to its original mode.

STREAMS/UX does not support mixing MP scalable and UP emulation modules in an upper mux because an upper mux is a clonable device. STREAMS/UX does not detect that upper mux streams are related. In particular, STREAMS/UX does not support pushing a UP emulation module onto only one MP scalable upper mux stream. STREAMS/UX changes only this one stream to run under UP emulation. It does not change the control stream or the other upper mux streams. You should design your modules and drivers so that only MP scalable modules are pushed onto MP scalable upper muxes. Also, STREAMS/UX does not support linking a UP emulation driver under an MP scalable upper mux. STREAMS/UX only changes the control stream to run under UP emulation. It does not change the other upper mux streams. You should link only MP scalable drivers under an MP scalable upper mux.

Some examples of supported streams configurations which contain both MP scalable and UP emulation modules and drivers are listed below.

  • If an MP scalable driver is linked under a UP emulation mux, STREAMS/UX changes the MP scalable driver to run in UP emulation mode. For example, DLPI is MP scalable in 10.0. When it is linked under UP emulation SNA, STREAMS/UX changes the drivers to run in UP emulation mode.

  • When an MP scalable module is pushed onto a UP emulation stream, STREAMS/UX runs the module under UP emulation. For example, timod is MP scalable. When it is pushed onto a UP emulation OSI stream, it runs under UP emulation.

  • When a UP emulation module is pushed onto an MP scalable stream, STREAMS/UX changes the entire stream to run under UP emulation. For example, DLPI is MP scalable in Release 10.0. When UP emulation Portable Netware modules are pushed onto DLPI, the entire stream runs in UP emulation mode. Another example is STREAMS/UX pipes, which are MP scalable. If UP emulation modules are pushed onto a pipe, the pipe runs under UP emulation.

  • As described earlier in this section, all user bufcall callback functions are executed in UP emulation mode. If an MP scalable module calls bufcall, the callback routine runs under UP emulation. If the callback routine invokes a put procedure, the put procedure also runs in UP emulation mode. For example, the DLPI driver is MP scalable in 10.0 and calls bufcall. The bufcall callback function runs under UP emulation.

Performance

Performance of UP emulation modules and drivers will likely worsen as more processors are added to a system. If a large number of users will be running your modules and drivers on MP systems, you should probably modify the code to be MP scalable.

MP scalable modules that run over non-STREAMS/UX UP emulation drivers will be forced to run in UP emulation mode. You can achieve better performance by changing drivers to be MP scalable.

Guidelines for UP Emulation Modules and Drivers

  • It is easier to develop STREAMS/UX based software which runs completely under UP emulation or is completely MP scalable. Try to avoid mixing UP emulation and MP scalable modules and drivers in the same stream or multiplexor.

  • It may be safe for UP emulation modules and drivers to call MP scalable non-STREAMS software. The MP scalable software must be able to run while the I/O semaphore is held. Note that if a put or service routine calls non-STREAMS functions, these functions cannot acquire semaphores because this might cause the put or service routine to block.

  • Be careful with MP scalable non-STREAMS kernel code when calling UP emulation STREAMS/UX modules. It is better if the non-STREAMS code schedules a service routine instead of invoking a put procedure. Scheduling the service routine will wake up the UP emulation scheduler daemon to run the routine. The daemon acquires the I/O semaphore. If non-STREAMS code calls put, putnext, or streams_put, STREAMS/UX will not acquire either the I/O semaphore or the spl lock.

  • Modules and drivers which can run MP scalable and run under UP emulation must use queue or queue pair synchronization. An example of an MP scalable module which can run in UP emulation mode is timod. Although timod will be configured to be MP scalable, it is pushed onto many streams, some of which run in UP emulation mode.

  • Do not push a UP emulation module onto an MP scalable upper mux. Do not link a UP emulation driver under an MP scalable upper mux. It is better for the mux to contain either all MP scalable modules and drivers or all UP emulation modules and drivers.

  • The UP emulation scheduler runs differently from the uniprocessor scheduler. This may affect STREAMS application programs. On multiprocessor systems, the scheduler may not run a service routine before the process which scheduled the routine returns to user level.

  • UP emulation modules and drivers need to follow the guidelines in the "STREAMS/UX Uniprocessor Synchronization" section of Chapter 3.

© 1995 Hewlett-Packard Development Company, L.P.