[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3. Foundations

Every Hurd program accepts the following optional arguments:

`--help'

Display a brief usage message, then exit. This message is not a substitute for reading program documentation; rather, it provides useful reminders about specific command-line options that a program understands.

`--version'

Output program version information and exit.

The rest of this chapter provides a programmer's introduction to the Hurd. If you are not a programmer, then this chapter will not make much sense to you… you should consider skipping to descriptions of specific Hurd programs (see section Audience).

The Hurd distribution includes many libraries in order to provide a useful set of tools for writing Hurd utilities and servers. Several of these libraries are useful not only for the Hurd, but also for writing microkernel-based programs in general. These fundamental libraries are not difficult to understand, and they are a good starting point, because the rest of the Hurd relies upon them quite heavily.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1 Threads Library

All Hurd servers and libraries are aggressively multithreaded in order to take full advantage of any multiprocessing capabilities provided by the microkernel and the underlying hardware. The Hurd threads library, libthreads, contains the default Hurd thread implementation, which is declared in <cthreads.h>.

Currently (April 1998), the Hurd uses cthreads, which have already been documented thoroughly by CMU. Eventually, it will be migrated to use POSIX pthreads, which are documented in a lot of places.

Every single library in the Hurd distribution (including the GNU C library) is completely thread-safe, and the Hurd servers themselves are aggressively multithreaded.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2 Ports Library

Ports are communication channels that are held by the kernel.

A port has separate send rights and receive rights, which may be transferred from task to task via the kernel. Port rights are similar to Unix file descriptors: they are per-task integers which are used to identify ports when making kernel calls. Send rights are required in order to send an RPC request down a port, and receive rights are required to serve the RPC request. Receive rights may be aggregated into a single portset, which serve as useful organizational units.

In a single-threaded RPC client, managing and categorizing ports is not a difficult process. However, in a complex multithreaded server, it is useful to have a more abstract interface to managing portsets, as well as maintaining server metadata.

The Hurd ports library, libports, fills that need. The libports functions are declared in <hurd/ports.h>.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2.1 Buckets and Classes

The libports bucket is simply a port set, with some metadata and a lock. All of the libports functions operate on buckets.

Function: struct port_bucket * ports_create_bucket (void)

Create and return a new, empty bucket.

A port class is a collection of individual ports, which can be manipulated conveniently, and have enforced deallocation routines. Buckets and classes are entirely orthogonal: there is no requirement that all the ports in a class be in the same bucket, nor is there a requirement that all the ports in a bucket be in the same class.

Function: struct port_class ports_create_class (void (*clean_routine) (void *port), void (*dropweak_routine) (void *port))

Create and return a new port class. If nonzero, clean_routine will be called for each allocated port object in this class when it is being destroyed. If nonzero, dropweak_routine will be called to request weak references to be dropped. (If dropweak_routine is null, then weak references and hard references will be identical for ports of this class.)

Once you have created at least one bucket and class, you may create new ports, and store them in those buckets. There are a few different functions for port creation, depending on your application's requirements:

Function: error_t ports_create_port (struct port_class *class, struct port_bucket *bucket, size_t size, void *result)

Create and return in result a new port in class and bucket; size bytes will be allocated to hold the port structure and whatever private data the user desires.

Function: error_t ports_create_port_noinstall (struct port_class *class, struct port_bucket *bucket, size_t size, void *result)

Just like ports_create_port, except don't actually put the port into the portset underlying bucket. This is intended to be used for cases where the port right must be given out before the port is fully initialized; with this call you are guaranteed that no RPC service will occur on the port until you have finished initializing it and installed it into the portset yourself.

Function: error_t ports_import_port (struct port_class *class, struct port_bucket *bucket, mach_port_t port, size_t size, void *result)

For an existing receive right, create and return in result a new port structure; bucket, size, and class args are as for ports_create_port.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2.2 Port Rights

The following functions move port receive rights to and from the port structure:

Function: void ports_reallocate_port (void *port)

Destroy the receive right currently associated with port and allocate a new one.

Function: void ports_reallocate_from_external (void *port, mach_port_t receive)

Destroy the receive right currently associated with port and designate receive as the new one.

Function: void ports_destroy_right (void *port)

Destroy the receive right currently associated with port. After this call, ports_reallocate_port and ports_reallocate_from_external may not be used.

Function: mach_port_t ports_claim_right (void *port)

Return the receive right currently associated with port. The effects on port are the same as in ports_destroy_right, except that the receive right itself is not affected. Note that in multi-threaded servers, messages might already have been dequeued for this port before it gets removed from the portset; such messages will get EOPNOTSUPP errors.

Function: error_t ports_transfer_right (void *topt, void *frompt)

Transfer the receive right from frompt to topt. frompt ends up with a destroyed right (as if ports_destroy_right were called) and topt's old right is destroyed (as if ports_reallocate_from_external were called).

Function: mach_port_t ports_get_right (void *port)

Return the name of the receive right associated with port. The user is responsible for creating an ordinary send right from this name.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2.3 Port Metadata

It is important to point out that the port argument to each of the libports functions is a void * and not a struct port_info *. This is done so that you may add arbitrary meta-information to your libports-managed ports. Simply define your own structure whose first element is a struct port_info, and then you can use pointers to these structures as the port argument to any libports function.

The following functions are useful for maintaining metadata that is stored in your own custom ports structure:

Function: void * ports_lookup_port (struct port_bucket *bucket, mach_port_t port, struct port_class *class)

Look up port and return the associated port structure, allocating a reference. If the call fails, return zero. If bucket is nonzero, then it specifies a bucket to search; otherwise all buckets will be searched. If class is nonzero, then the lookup will fail if port is not in class.

Function: error_t ports_bucket_iterate (struct port_bucket *bucket, error_t (*fun) (void *port))

Call fun once for each port in bucket. No guarantee is made about the order of iteration, which might vary from call to call. If FUN returns an error, then no further calls to FUN are made for any remaining ports, and the return value of FUN is returned from ports_bucket_iterate.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2.4 Port References

These functions maintain references to ports so that the port information structures may be freed if and only if they are no longer needed. It is your responsibility to tell libports when references to ports change.

Function: void ports_port_ref (void *port)

Allocate a hard reference to port.

Function: void ports_port_deref (void *port)

Drop a hard reference to port.

Function: void ports_no_senders (void *port, mach_port_mscount_t mscount)

The user is responsible for listening for no senders notifications; when one arrives, call this routine for the port the message was sent to, providing the mscount from the notification.

Function: int ports_count_class (struct port_class *class)

Block creation of new ports in class. Return the number of ports currently in class.

Function: int ports_count_bucket (struct port_bucket *bucket)

Block creation of new ports in bucket. Return the number of ports currently in bucket.

Function: void ports_enable_class (struct port_class *class)

Permit suspended port creation (blocked by ports_count_class) to continue.

Function: void ports_enable_bucket (struct port_bucket *bucket)

Permit suspended port creation (blocked by ports_count_bucket) to continue.

Weak references are not often used, as they are the same as hard references for port classes where dropweak_routine is null. See section Buckets and Classes.

Function: void ports_port_ref_weak (void *port)

Allocate a weak reference to port.

Function: void ports_port_deref_weak (void *port)

Drop a weak reference to port.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2.5 RPC Management

The rest of the libports functions are dedicated to controlling RPC operations. These functions help you do all the locking and thread cancellations that are required in order to build robust servers.

Typedef: typedef int (*ports_demuxer_type) (mach_msg_header_t *inp, mach_msg_header_t *outp)

Type of MiG demuxer routines.

Function: error_t ports_begin_rpc (void *port, mach_msg_id_t msg_id, struct rpc_info *info)

Call this when an RPC is beginning on port. info should be allocated by the caller and will be used to hold dynamic state. If this RPC should be abandoned, return EDIED; otherwise we return zero.

Function: void ports_end_rpc (void *port, struct rpc_info *info)

Call this when an RPC is concluding. The arguments must match the ones passed to the paired call to ports_begin_rpc.

Function: void ports_manage_port_operations_one_thread (struct port_bucket *bucket, ports_demuxer_type demuxer, int timeout)

Begin handling operations for the ports in bucket, calling demuxer for each incoming message. Return if timeout is nonzero and no messages have been received for timeout milliseconds. Use only one thread (the calling thread).

Function: void ports_manage_port_operations_multithread (struct port_bucket *bucket, ports_demuxer_type demuxer, int thread_timeout, int global_timeout, void (*hook) (void))

Begin handling operations for the ports in bucket, calling demuxer for each incoming message. Return if global_timeout is nonzero and no messages have been received for global_timeout milliseconds. Create threads as necessary to handle incoming messages so that no port is starved because of sluggishness on another port. If thread_timeout is nonzero, then individual threads will die off if they handle no incoming messages for local_timeout milliseconds. If non-null, hook will be called in each new thread immediately after it is created.

Function: error_t ports_inhibit_port_rpcs (void *port)

Interrupt any pending RPC on port. Wait for all pending RPCs to finish, and then block any new RPCs starting on that port.

Function: error_t ports_inhibit_class_rpcs (struct port_class *class)

Similar to ports_inhibit_port_rpcs, but affects all ports in class.

Function: error_t ports_inhibit_bucket_rpcs (struct port_bucket *bucket)

Similar to ports_inhibit_port_rpcs, but affects all ports in bucket.

Function: error_t ports_inhibit_all_rpcs (void)

Similar to ports_inhibit_port_rpcs, but affects all ports whatsoever.

Function: void ports_resume_port_rpcs (void *port)

Reverse the effect of a previous ports_inhibit_port_rpcs for this port, allowing blocked RPCs to continue.

Function: void ports_resume_class_rpcs (struct port_class *class)

Reverse the effect of a previous ports_inhibit_class_rpcs for class.

Function: void ports_resume_bucket_rpcs (struct port_bucket *bucket)

Reverse the effect of a previous ports_inhibit_bucket_rpcs for bucket.

Function: void ports_resume_all_rpcs (void)

Reverse the effect of a previous ports_inhibit_all_rpcs.

Function: void ports_interrupt_rpcs (void *port)

Cancel (with thread_cancel) any RPCs in progress on port.

Function: int ports_self_interrupted (void)

If the current thread's RPC has been interrupted with ports_interrupt_rpcs, return nonzero and clear the interrupted flag.

Function: error_t ports_interrupt_rpc_on_notification (void *object, struct rpc_info *rpc, mach_port_t port, mach_msg_id_t what)

Arrange for hurd_cancel to be called on rpc's thread if object gets notified that any of the things in what have happened to port. rpc should be an RPC on object.

Function: error_t ports_interrupt_self_on_notification (void *object, mach_port_t port, mach_msg_id_t what)

Arrange for hurd_cancel to be called on the current thread, which should be an RPC on object, if port gets notified with the condition what.

Function: error_t ports_interrupt_self_on_port_death (void *object, mach_port_t port)

Same as calling ports_interrupt_self_on_notification with what set to MACH_NOTIFY_DEAD_NAME.

Function: void ports_interrupt_notified_rpcs (void *object, mach_port_t port, mach_msg_id_t what)

Interrupt any RPCs on object that have requested such.

Function: void ports_dead_name (void *object, mach_port_t port)

Same as calling ports_interrupt_notified_rpcs with what set to MACH_NOTIFY_DEAD_NAME.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3 Integer Hash Library

libihash provides integer-keyed hash tables, for arbitrary element data types. Such hash tables are frequently used when implementing sparse arrays or buffer caches.

The following functions are declared in <hurd/ihash.h>:

Function: error_t ihash_create (ihash_t *ht)

Create an integer hash table and return it in ht. If a memory allocation error occurs, ENOMEM is returned, otherwise zero.

Function: void ihash_free (ihash_t ht)

Free ht and all resources it consumes.

Function: void ihash_set_cleanup (ihash_t ht, void (*cleanup) (void *value, void *arg), void *arg)

Sets ht's element cleanup function to cleanup, and its second argument to arg. cleanup will be called on every element value to be subsequently overwritten or deleted, with arg as the second argument.

Function: error_t ihash_add (ihash_t ht, int id, void *item, void ***locp)

Add item to the hash table ht under the integer key id. locp is the address of a pointer located in item; If non-null, locp should point to a variable of type void **, and will be filled with a pointer that may be used as an argument to ihash_locp_remove. The variable pointed to by locp may be overwritten sometime between this call and when the element is deleted, so you cannot stash its value elsewhere and hope to use the stashed value with ihash_locp_remove. If a memory allocation error occurs, ENOMEM is returned, otherwise zero.

Function: void * ihash_find (ihash_t ht, int id)

Find and return the item in hash table ht with key id. Returns null if the specified item doesn't exist.

Function: error_t ihash_iterate (ihash_t ht, error_t (*fun) (void *value))

Call function fun on every element of ht. fun's only arg, value, is a pointer to the value stored in the hash table. If fun ever returns nonzero, then iteration stops and ihash_iterate returns that value, otherwise it (eventually) returns 0.

Function: int ihash_remove (ihash_t ht, int id)

Remove the entry with a key of id from ht. If there was no such element, then return zero, otherwise nonzero.

Function: void ihash_locp_remove (ihash_t ht, void **ht_locp)

Remove the entry at locp from the hashtable ht. locp is as returned from an earlier call to ihash_add. This call should be faster than ihash_remove. ht can be null, in which case the call still succeeds, but no cleanup is done.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4 Misc Library

The GNU C library is constantly developing to meet the needs of the Hurd. However, because the C library needs to be very stable, it is irresponsible to add new functions to it without carefully specifying their interface, and testing them thoroughly.

The Hurd distribution includes a library called libshouldbeinlibc, which serves as a proving ground for additions to the GNU C library. This library is in flux, as some functions are added to it by the Hurd developers and others are moved to the official C library.

These functions aren't currently documented (other than in their header files), but complete documentation will be added to when these functions become part of the GNU C library.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.5 Bug Address Library

libhurdbugaddr exists only to define a single variable:

Variable: char * argp_program_bug_address

argp_program_bug_address is the default Hurd bug-reporting e-mail address, [email protected]. This address is displayed to the user when any of the standard Hurd servers and utilities are invoked using the `--help' option.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Thomas Schwinge on November, 8 2007 using texi2html 1.76.