summaryrefslogtreecommitdiff
path: root/debian/patches/extern_inline_fix.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/extern_inline_fix.patch')
-rw-r--r--debian/patches/extern_inline_fix.patch734
1 files changed, 734 insertions, 0 deletions
diff --git a/debian/patches/extern_inline_fix.patch b/debian/patches/extern_inline_fix.patch
new file mode 100644
index 00000000..b9eacbff
--- /dev/null
+++ b/debian/patches/extern_inline_fix.patch
@@ -0,0 +1,734 @@
+Use libc's __extern_inline which works properly according to optimization flags
+---
+ libdiskfs/diskfs.h | 17 ++++++----
+ libpipe/pipe.h | 74 ++++++++++++++++++++++++++++++++------------
+ libpipe/pq.h | 57 ++++++++++++++++++++++++++-------
+ libshouldbeinlibc/idvec.h | 29 ++++++++++++-----
+ libshouldbeinlibc/maptime.h | 13 ++++---
+ libshouldbeinlibc/ugids.h | 25 ++++++++++----
+ libstore/store.h | 13 ++++---
+ libthreads/rwlock.h | 27 +++++++++++-----
+ 8 files changed, 184 insertions(+), 71 deletions(-)
+
+--- a/libdiskfs/diskfs.h
++++ b/libdiskfs/diskfs.h
+@@ -27,10 +27,7 @@
+ #include <hurd/fshelp.h>
+ #include <hurd/iohelp.h>
+ #include <idvec.h>
+-
+-#ifndef DISKFS_EXTERN_INLINE
+-#define DISKFS_EXTERN_INLINE extern inline
+-#endif
++#include <features.h>
+
+ /* Each user port referring to a file points to one of these
+ (with the aid of the ports library). */
+@@ -781,10 +778,16 @@ error_t diskfs_start_protid (struct pero
+ the user to install is USER. */
+ void diskfs_finish_protid (struct protid *cred, struct iouser *user);
+
++extern struct protid * diskfs_begin_using_protid_port (file_t port);
++
++extern void diskfs_end_using_protid_port (struct protid *cred);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Called by MiG to translate ports into struct protid *.
+ fsmutations.h arranges for this to happen for the io and
+ fs interfaces. */
+-DISKFS_EXTERN_INLINE struct protid *
++__extern_inline struct protid *
+ diskfs_begin_using_protid_port (file_t port)
+ {
+ return ports_lookup_port (diskfs_port_bucket, port, diskfs_protid_class);
+@@ -793,13 +796,15 @@ diskfs_begin_using_protid_port (file_t p
+ /* Called by MiG after server routines have been run; this
+ balances begin_using_protid_port, and is arranged for the io
+ and fs interfaces by fsmutations.h. */
+-DISKFS_EXTERN_INLINE void
++__extern_inline void
+ diskfs_end_using_protid_port (struct protid *cred)
+ {
+ if (cred)
+ ports_port_deref (cred);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Called when a protid CRED has no more references. (Because references\
+ to protids are maintained by the port management library, this is
+ installed in the clean routines list.) The ports library will
+--- a/libpipe/pipe.h
++++ b/libpipe/pipe.h
+@@ -24,13 +24,10 @@
+ #define EWOULDBLOCK EAGAIN /* XXX */
+
+ #include <cthreads.h> /* For conditions & mutexes */
++#include <features.h>
+
+ #include "pq.h"
+
+-#ifndef PIPE_EI
+-#define PIPE_EI extern inline
+-#endif
+-
+
+ /* A description of a class of pipes and how to operate on them. */
+ struct pipe_class
+@@ -107,9 +104,24 @@ struct pipe
+ /* Pipe flags. */
+ #define PIPE_BROKEN 0x1 /* This pipe isn't connected. */
+
++
++extern size_t pipe_readable (struct pipe *pipe, int data_only);
++
++extern int pipe_is_readable (struct pipe *pipe, int data_only);
++
++extern error_t pipe_wait_readable (struct pipe *pipe, int noblock, int data_only);
++
++extern error_t pipe_select_readable (struct pipe *pipe, int data_only);
++
++extern error_t pipe_wait_writable (struct pipe *pipe, int noblock);
++
++extern error_t pipe_select_writable (struct pipe *pipe);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns the number of characters quickly readable from PIPE. If DATA_ONLY
+ is true, then `control' packets are ignored. */
+-PIPE_EI size_t
++__extern_inline size_t
+ pipe_readable (struct pipe *pipe, int data_only)
+ {
+ size_t readable = 0;
+@@ -128,7 +140,7 @@ pipe_readable (struct pipe *pipe, int da
+ then `control' packets are ignored. Note that this is different than
+ (pipe_readable (PIPE) > 0) in the case where a control packet containing
+ only ports is present. */
+-PIPE_EI int
++__extern_inline int
+ pipe_is_readable (struct pipe *pipe, int data_only)
+ {
+ struct pq *pq = pipe->queue;
+@@ -143,7 +155,7 @@ pipe_is_readable (struct pipe *pipe, int
+ this operation will return EWOULDBLOCK instead of blocking when no data is
+ immediately available. If DATA_ONLY is true, then `control' packets are
+ ignored. */
+-PIPE_EI error_t
++__extern_inline error_t
+ pipe_wait_readable (struct pipe *pipe, int noblock, int data_only)
+ {
+ while (! pipe_is_readable (pipe, data_only) && ! (pipe->flags & PIPE_BROKEN))
+@@ -160,7 +172,7 @@ pipe_wait_readable (struct pipe *pipe, i
+ returns once threads waiting using pipe_wait_readable have been woken and
+ given a chance to read, and if there is still data available thereafter.
+ If DATA_ONLY is true, then `control' packets are ignored. */
+-PIPE_EI error_t
++__extern_inline error_t
+ pipe_select_readable (struct pipe *pipe, int data_only)
+ {
+ while (! pipe_is_readable (pipe, data_only) && ! (pipe->flags & PIPE_BROKEN))
+@@ -172,7 +184,7 @@ pipe_select_readable (struct pipe *pipe,
+ /* Block until data can be written to PIPE. If NOBLOCK is true, then
+ EWOULDBLOCK is returned instead of blocking if this can't be done
+ immediately. */
+-PIPE_EI error_t
++__extern_inline error_t
+ pipe_wait_writable (struct pipe *pipe, int noblock)
+ {
+ size_t limit = pipe->write_limit;
+@@ -193,7 +205,7 @@ pipe_wait_writable (struct pipe *pipe, i
+ /* Block until some data can be written to PIPE. This call only returns once
+ threads waiting using pipe_wait_writable have been woken and given a
+ chance to write, and if there is still space available thereafter. */
+-PIPE_EI error_t
++__extern_inline error_t
+ pipe_select_writable (struct pipe *pipe)
+ {
+ size_t limit = pipe->write_limit;
+@@ -203,6 +215,8 @@ pipe_select_writable (struct pipe *pipe)
+ return 0;
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Creates a new pipe of class CLASS and returns it in RESULT. */
+ error_t pipe_create (struct pipe_class *class, struct pipe **pipe);
+
+@@ -223,8 +237,28 @@ void _pipe_no_readers (struct pipe *pipe
+ should be locked. */
+ void _pipe_no_writers (struct pipe *pipe);
+
++extern void pipe_acquire_reader (struct pipe *pipe);
++
++extern void pipe_acquire_writer (struct pipe *pipe);
++
++extern void pipe_release_reader (struct pipe *pipe);
++
++extern void pipe_release_writer (struct pipe *pipe);
++
++extern void pipe_add_reader (struct pipe *pipe);
++
++extern void pipe_add_writer (struct pipe *pipe);
++
++extern void pipe_remove_reader (struct pipe *pipe);
++
++extern void pipe_remove_writer (struct pipe *pipe);
++
++extern void pipe_drain (struct pipe *pipe);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Lock PIPE and increment its readers count. */
+-PIPE_EI void
++__extern_inline void
+ pipe_acquire_reader (struct pipe *pipe)
+ {
+ mutex_lock (&pipe->lock);
+@@ -233,7 +267,7 @@ pipe_acquire_reader (struct pipe *pipe)
+ }
+
+ /* Lock PIPE and increment its writers count. */
+-PIPE_EI void
++__extern_inline void
+ pipe_acquire_writer (struct pipe *pipe)
+ {
+ mutex_lock (&pipe->lock);
+@@ -243,7 +277,7 @@ pipe_acquire_writer (struct pipe *pipe)
+
+ /* Decrement PIPE's (which should be locked) reader count and unlock it. If
+ there are no more refs to PIPE, it will be destroyed. */
+-PIPE_EI void
++__extern_inline void
+ pipe_release_reader (struct pipe *pipe)
+ {
+ if (--pipe->readers == 0)
+@@ -254,7 +288,7 @@ pipe_release_reader (struct pipe *pipe)
+
+ /* Decrement PIPE's (which should be locked) writer count and unlock it. If
+ there are no more refs to PIPE, it will be destroyed. */
+-PIPE_EI void
++__extern_inline void
+ pipe_release_writer (struct pipe *pipe)
+ {
+ if (--pipe->writers == 0)
+@@ -264,7 +298,7 @@ pipe_release_writer (struct pipe *pipe)
+ }
+
+ /* Increment PIPE's reader count. PIPE should be unlocked. */
+-PIPE_EI void
++__extern_inline void
+ pipe_add_reader (struct pipe *pipe)
+ {
+ pipe_acquire_reader (pipe);
+@@ -272,7 +306,7 @@ pipe_add_reader (struct pipe *pipe)
+ }
+
+ /* Increment PIPE's writer count. PIPE should be unlocked. */
+-PIPE_EI void
++__extern_inline void
+ pipe_add_writer (struct pipe *pipe)
+ {
+ pipe_acquire_writer (pipe);
+@@ -281,7 +315,7 @@ pipe_add_writer (struct pipe *pipe)
+
+ /* Decrement PIPE's (which should be unlocked) reader count and unlock it. If
+ there are no more refs to PIPE, it will be destroyed. */
+-PIPE_EI void
++__extern_inline void
+ pipe_remove_reader (struct pipe *pipe)
+ {
+ mutex_lock (&pipe->lock);
+@@ -290,7 +324,7 @@ pipe_remove_reader (struct pipe *pipe)
+
+ /* Decrement PIPE's (which should be unlocked) writer count and unlock it. If
+ there are no more refs to PIPE, it will be destroyed. */
+-PIPE_EI void
++__extern_inline void
+ pipe_remove_writer (struct pipe *pipe)
+ {
+ mutex_lock (&pipe->lock);
+@@ -298,12 +332,14 @@ pipe_remove_writer (struct pipe *pipe)
+ }
+
+ /* Empty out PIPE of any data. PIPE should be locked. */
+-PIPE_EI void
++__extern_inline void
+ pipe_drain (struct pipe *pipe)
+ {
+ pq_drain (pipe->queue);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Writes up to LEN bytes of DATA, to PIPE, which should be locked, and
+ returns the amount written in AMOUNT. If present, the information in
+ CONTROL & PORTS is written in a preceding control packet. If an error is
+--- a/libpipe/pq.h
++++ b/libpipe/pq.h
+@@ -25,10 +25,7 @@
+ #include <stddef.h> /* for size_t */
+ #include <string.h>
+ #include <mach/mach.h>
+-
+-#ifndef PQ_EI
+-#define PQ_EI extern inline
+-#endif
++#include <features.h>
+
+
+ struct packet
+@@ -70,13 +67,19 @@ error_t packet_set_ports (struct packet
+ /* If PACKET has any ports, deallocates them. */
+ void packet_dealloc_ports (struct packet *packet);
+
++extern size_t packet_readable (struct packet *packet);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns the number of bytes of data in PACKET. */
+-PQ_EI size_t
++__extern_inline size_t
+ packet_readable (struct packet *packet)
+ {
+ return packet->buf_end - packet->buf_start;
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Append the bytes in DATA, of length DATA_LEN, to what's already in PACKET,
+ and return the amount appended in AMOUNT if that's not the null pointer. */
+ error_t packet_write (struct packet *packet,
+@@ -94,14 +97,20 @@ error_t packet_read (struct packet *pack
+ error_t packet_read_ports (struct packet *packet,
+ mach_port_t **ports, size_t *num_ports);
+
++extern void packet_read_source (struct packet *packet, void **source);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Return the source addressd in PACKET in SOURCE, deallocating it from
+ PACKET. */
+-PQ_EI void
++__extern_inline void
+ packet_read_source (struct packet *packet, void **source)
+ {
+ *source = packet->source;
+ packet->source = 0;
+ }
++
++# endif /* Use extern inlines. */
+
+ /* The packet size above which we start to do things differently to avoid
+ copying around data. */
+@@ -125,9 +134,17 @@ int packet_extend (struct packet *packet
+ returned. */
+ error_t packet_realloc (struct packet *packet, size_t new_len);
+
++extern int packet_fit (struct packet *packet, size_t amount);
++
++extern error_t packet_ensure (struct packet *packet, size_t amount);
++
++extern int packet_ensure_efficiently (struct packet *packet, size_t amount);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Try to make space in PACKET for AMOUNT more bytes without growing the
+ buffer, returning true if we could do it. */
+-PQ_EI int
++__extern_inline int
+ packet_fit (struct packet *packet, size_t amount)
+ {
+ char *buf = packet->buf, *end = packet->buf_end;
+@@ -159,7 +176,7 @@ packet_fit (struct packet *packet, size_
+
+ /* Make sure that PACKET has room for at least AMOUNT more bytes, or return
+ the reason why not. */
+-PQ_EI error_t
++__extern_inline error_t
+ packet_ensure (struct packet *packet, size_t amount)
+ {
+ if (! packet_fit (packet, amount))
+@@ -176,7 +193,7 @@ packet_ensure (struct packet *packet, si
+ it can be done efficiently, e.g., the packet can be grown in place, rather
+ than moving the contents (or there is little enough data so that copying
+ it is OK). True is returned if room was made, false otherwise. */
+-PQ_EI int
++__extern_inline int
+ packet_ensure_efficiently (struct packet *packet, size_t amount)
+ {
+ if (! packet_fit (packet, amount))
+@@ -189,6 +206,8 @@ packet_ensure_efficiently (struct packet
+ }
+ return 0;
+ }
++
++# endif /* Use extern inlines. */
+
+ struct pq
+ {
+@@ -201,10 +220,14 @@ struct pq
+ the packet, or deallocated by calling pipe_dealloc_addr. */
+ struct packet *pq_queue (struct pq *pq, unsigned type, void *source);
+
++extern struct packet * pq_tail (struct pq *pq, unsigned type, void *source);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns the tail of the packet queue PQ, which may mean pushing a new
+ packet if TYPE and SOURCE do not match the current tail, or this is the
+ first packet. */
+-PQ_EI struct packet *
++__extern_inline struct packet *
+ pq_tail (struct pq *pq, unsigned type, void *source)
+ {
+ struct packet *tail = pq->tail;
+@@ -214,16 +237,24 @@ pq_tail (struct pq *pq, unsigned type, v
+ return tail;
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Remove the first packet (if any) in PQ, deallocating any resources it
+ holds. True is returned if a packet was found, false otherwise. */
+ int pq_dequeue (struct pq *pq);
+
++extern struct packet * pq_head (struct pq *pq, unsigned type, void *source);
++
++extern struct packet * pq_next (struct pq *pq, unsigned type, void *source);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns the next available packet in PQ, without removing it from the
+ queue, or NULL if there is none, or the next packet isn't appropriate.
+ A packet is inappropriate if SOURCE is non-NULL its source field doesn't
+ match it, or TYPE is non-NULL and the packet's type field doesn't match
+ it. */
+-PQ_EI struct packet *
++__extern_inline struct packet *
+ pq_head (struct pq *pq, unsigned type, void *source)
+ {
+ struct packet *head = pq->head;
+@@ -237,7 +268,7 @@ pq_head (struct pq *pq, unsigned type, v
+ }
+
+ /* The same as pq_head, but first discards the head of the queue. */
+-PQ_EI struct packet *
++__extern_inline struct packet *
+ pq_next (struct pq *pq, unsigned type, void *source)
+ {
+ if (!pq->head)
+@@ -246,6 +277,8 @@ pq_next (struct pq *pq, unsigned type, v
+ return pq_head (pq, type, source);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Dequeues all packets in PQ. */
+ void pq_drain (struct pq *pq);
+
+--- a/libshouldbeinlibc/idvec.h
++++ b/libshouldbeinlibc/idvec.h
+@@ -24,10 +24,7 @@
+ #include <hurd/hurd_types.h>
+ #include <errno.h>
+ #include <string.h>
+-
+-#ifndef IDVEC_EI
+-#define IDVEC_EI extern inline
+-#endif
++#include <features.h>
+
+ struct idvec
+ {
+@@ -50,22 +47,30 @@ void idvec_free_wrapper (struct idvec *i
+ /* Free IDVEC and any storage associated with it. */
+ void idvec_free (struct idvec *idvec);
+
++extern void idvec_clear (struct idvec *idvec);
++
++extern int idvec_is_empty (const struct idvec *idvec);
++
++extern int idvec_equal (const struct idvec *idvec1, const struct idvec *idvec2);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Mark IDVEC as not containing any ids. */
+-IDVEC_EI void
++__extern_inline void
+ idvec_clear (struct idvec *idvec)
+ {
+ idvec->num = 0;
+ }
+
+ /* Returns true if IDVEC contains no ids. */
+-IDVEC_EI int
++__extern_inline int
+ idvec_is_empty (const struct idvec *idvec)
+ {
+ return idvec->num == 0;
+ }
+
+ /* Return true if IDVEC1 has contents identical to IDVEC2. */
+-IDVEC_EI int
++__extern_inline int
+ idvec_equal (const struct idvec *idvec1, const struct idvec *idvec2)
+ {
+ size_t num = idvec1->num;
+@@ -74,6 +79,8 @@ idvec_equal (const struct idvec *idvec1,
+ || memcmp (idvec1->ids, idvec2->ids, num * sizeof *idvec1->ids) == 0);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Ensure that IDVEC has enough spaced allocated to hold NUM ids, thus
+ ensuring that any subsequent ids added won't return a memory allocation
+ error unless it would result in more ids that NUM. ENOMEM is returned if
+@@ -87,13 +94,19 @@ error_t idvec_grow (struct idvec *idvec,
+ /* Returns true if IDVEC contains ID, at or after position POS. */
+ int idvec_tail_contains (const struct idvec *idvec, unsigned pos, uid_t id);
+
++extern int idvec_contains (const struct idvec *idvec, uid_t id);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns true if IDVEC contains ID. */
+-IDVEC_EI int
++__extern_inline int
+ idvec_contains (const struct idvec *idvec, uid_t id)
+ {
+ return idvec_tail_contains (idvec, 0, id);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Insert ID into IDVEC at position POS, returning ENOMEM if there wasn't
+ enough memory, or 0. */
+ error_t idvec_insert (struct idvec *idvec, unsigned pos, uid_t id);
+--- a/libshouldbeinlibc/maptime.h
++++ b/libshouldbeinlibc/maptime.h
+@@ -21,13 +21,10 @@
+ #ifndef __MAPTIME_H__
+ #define __MAPTIME_H__
+
+-#ifndef MAPTIME_EI
+-#define MAPTIME_EI extern inline
+-#endif
+-
+ #include <mach/time_value.h>
+ #include <sys/time.h>
+ #include <errno.h>
++#include <features.h>
+
+ /* Return the mach mapped time page in MTIME. If USE_MACH_DEV is false, then
+ the hurd time device DEV_NAME, or "/dev/time" if DEV_NAME is 0, is
+@@ -37,8 +34,12 @@
+ error_t maptime_map (int use_mach_dev, char *dev_name,
+ volatile struct mapped_time_value **mtime);
+
++extern void maptime_read (volatile struct mapped_time_value *mtime, struct timeval *tv);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Read the current time from MTIME into TV. This should be very fast. */
+-MAPTIME_EI void
++__extern_inline void
+ maptime_read (volatile struct mapped_time_value *mtime, struct timeval *tv)
+ {
+ do
+@@ -49,4 +50,6 @@ maptime_read (volatile struct mapped_tim
+ while (tv->tv_sec != mtime->check_seconds);
+ }
+
++# endif /* Use extern inlines. */
++
+ #endif /* __MAPTIME_H__ */
+--- a/libshouldbeinlibc/ugids.h
++++ b/libshouldbeinlibc/ugids.h
+@@ -23,10 +23,7 @@
+
+ #include <stdlib.h> /* For inline function stuff. */
+ #include <idvec.h>
+-
+-#ifndef UGIDS_EI
+-#define UGIDS_EI extern inline
+-#endif
++#include <features.h>
+
+ /* A structure holding a set of the common various types of ids. */
+ struct ugids
+@@ -47,8 +44,18 @@ struct ugids
+ /* Return a new ugids structure, or 0 if an allocation error occurs. */
+ struct ugids *make_ugids ();
+
++extern void ugids_fini (struct ugids *ugids);
++
++extern void ugids_free (struct ugids *ugids);
++
++extern int ugids_is_empty (const struct ugids *ugids);
++
++extern int ugids_equal (const struct ugids *ugids1, const struct ugids *ugids2);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Free all resources used by UGIDS except UGIDS itself. */
+-UGIDS_EI void
++__extern_inline void
+ ugids_fini (struct ugids *ugids)
+ {
+ idvec_fini (&ugids->eff_uids);
+@@ -60,7 +67,7 @@ ugids_fini (struct ugids *ugids)
+ }
+
+ /* Free all resources used by UGIDS. */
+-UGIDS_EI void
++__extern_inline void
+ ugids_free (struct ugids *ugids)
+ {
+ ugids_fini (ugids);
+@@ -68,7 +75,7 @@ ugids_free (struct ugids *ugids)
+ }
+
+ /* Return true if UGIDS contains no ids. */
+-UGIDS_EI int
++__extern_inline int
+ ugids_is_empty (const struct ugids *ugids)
+ {
+ /* We needn't test the imp_*_gids vectors because they are subsets of the
+@@ -81,7 +88,7 @@ ugids_is_empty (const struct ugids *ugid
+ }
+
+ /* Free all resources used by UGIDS except UGIDS itself. */
+-UGIDS_EI int
++__extern_inline int
+ ugids_equal (const struct ugids *ugids1, const struct ugids *ugids2)
+ {
+ return
+@@ -93,6 +100,8 @@ ugids_equal (const struct ugids *ugids1,
+ && idvec_equal (&ugids1->imp_avail_gids, &ugids2->imp_avail_gids);
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Add all ids in NEW to UGIDS. */
+ error_t ugids_merge (struct ugids *ugids, const struct ugids *new);
+
+--- a/libstore/store.h
++++ b/libstore/store.h
+@@ -33,10 +33,7 @@
+ #include <mach.h>
+ #include <device/device.h>
+ #include <hurd/hurd_types.h>
+-
+-#ifndef STORE_EI
+-#define STORE_EI extern inline
+-#endif
++#include <features.h>
+
+
+ /* Type for addresses inside the store. */
+@@ -270,9 +267,13 @@ error_t store_set_child_flags (struct st
+ STORE's flags. */
+ error_t store_clear_child_flags (struct store *store, int flags);
+
++extern int store_is_securely_returnable (struct store *store, int open_flags);
++
++# ifdef __USE_EXTERN_INLINES
++
+ /* Returns true if STORE can safely be returned to a user who has accessed it
+ via a node using OPEN_FLAGS, without compromising security. */
+-STORE_EI int
++__extern_inline int
+ store_is_securely_returnable (struct store *store, int open_flags)
+ {
+ int flags = store->flags;
+@@ -283,6 +284,8 @@ store_is_securely_returnable (struct sto
+ || (flags & STORE_HARD_READONLY)));
+ }
+
++# endif /* Use extern inlines. */
++
+ /* Fills in the values of the various fields in STORE that are derivable from
+ the set of runs & the block size. */
+ void _store_derive (struct store *store);
+--- a/libthreads/rwlock.h
++++ b/libthreads/rwlock.h
+@@ -21,6 +21,7 @@
+
+ #include <cthreads.h>
+ #include <assert.h>
++#include <features.h>
+
+ struct rwlock
+ {
+@@ -31,12 +32,20 @@ struct rwlock
+ int readers_waiting;
+ };
+
+-#ifndef RWLOCK_EI
+-#define RWLOCK_EI extern inline
+-#endif
++extern void rwlock_reader_lock (struct rwlock *lock);
++
++extern void rwlock_writer_lock (struct rwlock *lock);
++
++extern void rwlock_reader_unlock (struct rwlock *lock);
++
++extern void rwlock_writer_unlock (struct rwlock *lock);
++
++extern void rwlock_init (struct rwlock *lock);
++
++# ifdef __USE_EXTERN_INLINES
+
+ /* Get a reader lock on reader-writer lock LOCK for disknode DN */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_reader_lock (struct rwlock *lock)
+ {
+ mutex_lock (&lock->master);
+@@ -53,7 +62,7 @@ rwlock_reader_lock (struct rwlock *lock)
+ }
+
+ /* Get a writer lock on reader-writer lock LOCK for disknode DN */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_writer_lock (struct rwlock *lock)
+ {
+ mutex_lock (&lock->master);
+@@ -70,7 +79,7 @@ rwlock_writer_lock (struct rwlock *lock)
+ }
+
+ /* Release a reader lock on reader-writer lock LOCK for disknode DN */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_reader_unlock (struct rwlock *lock)
+ {
+ mutex_lock (&lock->master);
+@@ -82,7 +91,7 @@ rwlock_reader_unlock (struct rwlock *loc
+ }
+
+ /* Release a writer lock on reader-writer lock LOCK for disknode DN */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_writer_unlock (struct rwlock *lock)
+ {
+ mutex_lock (&lock->master);
+@@ -94,7 +103,7 @@ rwlock_writer_unlock (struct rwlock *loc
+ }
+
+ /* Initialize reader-writer lock LOCK */
+-RWLOCK_EI void
++__extern_inline void
+ rwlock_init (struct rwlock *lock)
+ {
+ mutex_init (&lock->master);
+@@ -104,6 +113,8 @@ rwlock_init (struct rwlock *lock)
+ lock->writers_waiting = 0;
+ }
+
++# endif /* Use extern inlines. */
++
+ #define RWLOCK_INITIALIZER \
+ { MUTEX_INITIALIZER, CONDITION_INITIALIZER, 0, 0, 0 }
+