Added BeOS files contributed by Matthew Zahorik <maz@albany.net>.
git-svn-id: svn://10.0.0.236/trunk@18533 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
20cff3e357
commit
5e0ff19bc7
31
mozilla/nsprpub/pr/src/bthreads/Makefile
Normal file
31
mozilla/nsprpub/pr/src/bthreads/Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (the "MPL"); you may not use this file except in
|
||||
# compliance with the MPL. You may obtain a copy of the MPL at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# MPL.
|
||||
#
|
||||
|
||||
#! gmake
|
||||
|
||||
MOD_DEPTH = ../../..
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
include bsrcs.mk
|
||||
CSRCS += $(BTCSRCS)
|
||||
|
||||
TARGETS = $(OBJS)
|
||||
|
||||
INCLUDES = -I$(DIST)/include/private -I$(DIST)/include
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
install:: export
|
||||
|
||||
25
mozilla/nsprpub/pr/src/bthreads/bsrcs.mk
Normal file
25
mozilla/nsprpub/pr/src/bthreads/bsrcs.mk
Normal file
@ -0,0 +1,25 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (the "MPL"); you may not use this file except in
|
||||
# compliance with the MPL. You may obtain a copy of the MPL at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# MPL.
|
||||
#
|
||||
|
||||
# this file lists the source files to be compiled (used in Makefile) and
|
||||
# then enumerated as object files (in objs.mk) for inclusion in the NSPR
|
||||
# shared library
|
||||
|
||||
BTCSRCS = \
|
||||
btthread.c \
|
||||
btlocks.c \
|
||||
btcvar.c \
|
||||
btmon.c \
|
||||
btsem.c \
|
||||
btcmon.c \
|
||||
btmisc.c \
|
||||
$(NULL)
|
||||
405
mozilla/nsprpub/pr/src/bthreads/btcmon.c
Normal file
405
mozilla/nsprpub/pr/src/bthreads/btcmon.c
Normal file
@ -0,0 +1,405 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include <kernel/OS.h>
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
/*
|
||||
** Most of this is ripped out of ../threads/prcmon.c
|
||||
*/
|
||||
|
||||
PRLock *_pr_mcacheLock;
|
||||
#define _PR_NEW_LOCK_MCACHE() (_pr_mcacheLock = PR_NewLock())
|
||||
#define _PR_LOCK_MCACHE() PR_Lock(_pr_mcacheLock)
|
||||
#define _PR_UNLOCK_MCACHE() PR_Unlock(_pr_mcacheLock)
|
||||
|
||||
typedef struct MonitorCacheEntryStr MonitorCacheEntry;
|
||||
|
||||
struct MonitorCacheEntryStr {
|
||||
MonitorCacheEntry* next;
|
||||
void* address;
|
||||
PRMonitor* mon;
|
||||
long cacheEntryCount;
|
||||
};
|
||||
|
||||
static PRUint32 hash_mask;
|
||||
static PRUintn num_hash_buckets;
|
||||
static PRUintn num_hash_buckets_log2;
|
||||
static MonitorCacheEntry **hash_buckets;
|
||||
static MonitorCacheEntry *free_entries;
|
||||
static PRUintn num_free_entries;
|
||||
static PRBool expanding;
|
||||
int _pr_mcache_ready;
|
||||
|
||||
#define HASH(address) \
|
||||
((PRUint32) ( ((PRUptrdiff)(address) >> 2) ^ \
|
||||
((PRUptrdiff)(address) >> 10) ) \
|
||||
& hash_mask)
|
||||
|
||||
/*
|
||||
** Expand the monitor cache. This grows the hash buckets and allocates a
|
||||
** new chunk of cache entries and throws them on the free list. We keep
|
||||
** as many hash buckets as there are entries.
|
||||
**
|
||||
** Because we call malloc and malloc may need the monitor cache, we must
|
||||
** ensure that there are several free monitor cache entries available for
|
||||
** malloc to get. FREE_THRESHOLD is used to prevent monitor cache
|
||||
** starvation during monitor cache expansion.
|
||||
*/
|
||||
|
||||
#define FREE_THRESHOLD 5
|
||||
|
||||
static PRStatus ExpandMonitorCache(PRUintn new_size_log2)
|
||||
{
|
||||
MonitorCacheEntry **old_hash_buckets, *p;
|
||||
PRUintn i, entries, old_num_hash_buckets, added;
|
||||
MonitorCacheEntry **new_hash_buckets, *new_entries;
|
||||
|
||||
entries = 1L << new_size_log2;
|
||||
|
||||
/*
|
||||
** Expand the monitor-cache-entry free list
|
||||
*/
|
||||
|
||||
new_entries = (MonitorCacheEntry*)PR_CALLOC(
|
||||
entries * sizeof(MonitorCacheEntry));
|
||||
if (NULL == new_entries) return PR_FAILURE;
|
||||
|
||||
/*
|
||||
** Allocate system monitors for the new monitor cache entries. If we
|
||||
** run out of system monitors, break out of the loop.
|
||||
*/
|
||||
for (i = 0, added = 0, p = new_entries; i < entries; i++, p++, added++)
|
||||
{
|
||||
p->mon = PR_NewMonitor();
|
||||
if (!p->mon) break;
|
||||
}
|
||||
if (added != entries)
|
||||
{
|
||||
if (added == 0)
|
||||
{
|
||||
/* Totally out of system monitors. Lossage abounds */
|
||||
PR_DELETE(new_entries);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
** We were able to allocate some of the system monitors. Use
|
||||
** realloc to shrink down the new_entries memory
|
||||
*/
|
||||
p = (MonitorCacheEntry*)PR_REALLOC(
|
||||
new_entries, added * sizeof(MonitorCacheEntry));
|
||||
if (p == 0)
|
||||
{
|
||||
/*
|
||||
** Total lossage. We just leaked a bunch of system monitors
|
||||
** all over the floor. This should never ever happen.
|
||||
*/
|
||||
PR_ASSERT(p != 0);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Now that we have allocated all of the system monitors, build up
|
||||
** the new free list. We can just update the free_list because we own
|
||||
** the mcache-lock and we aren't calling anyone who might want to use
|
||||
** it.
|
||||
*/
|
||||
for (i = 0, p = new_entries; i < added - 1; i++, p++) p->next = p + 1;
|
||||
p->next = free_entries;
|
||||
free_entries = new_entries;
|
||||
num_free_entries += added;
|
||||
|
||||
/* Try to expand the hash table */
|
||||
new_hash_buckets = (MonitorCacheEntry**)PR_CALLOC(
|
||||
entries * sizeof(MonitorCacheEntry*));
|
||||
if (NULL == new_hash_buckets)
|
||||
{
|
||||
/*
|
||||
** Partial lossage. In this situation we don't get any more hash
|
||||
** buckets, which just means that the table lookups will take
|
||||
** longer. This is bad, but not fatal
|
||||
*/
|
||||
PR_LOG(_pr_cmon_lm, PR_LOG_WARNING,
|
||||
("unable to grow monitor cache hash buckets"));
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute new hash mask value. This value is used to mask an address
|
||||
** until it's bits are in the right spot for indexing into the hash
|
||||
** table.
|
||||
*/
|
||||
hash_mask = entries - 1;
|
||||
|
||||
/*
|
||||
** Expand the hash table. We have to rehash everything in the old
|
||||
** table into the new table. */
|
||||
old_hash_buckets = hash_buckets;
|
||||
old_num_hash_buckets = num_hash_buckets;
|
||||
for (i = 0; i < old_num_hash_buckets; i++)
|
||||
{
|
||||
p = old_hash_buckets[i];
|
||||
while (p)
|
||||
{
|
||||
MonitorCacheEntry *next = p->next;
|
||||
|
||||
/* Hash based on new table size, and then put p in the new table
|
||||
*/
|
||||
PRUintn hash = HASH(p->address);
|
||||
p->next = new_hash_buckets[hash];
|
||||
new_hash_buckets[hash] = p;
|
||||
|
||||
p = next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Switch over to new hash table and THEN call free of the old
|
||||
** table. Since free might re-enter _pr_mcache_lock, things would
|
||||
** break terribly if it used the old hash table.
|
||||
*/
|
||||
|
||||
hash_buckets = new_hash_buckets;
|
||||
num_hash_buckets = entries;
|
||||
num_hash_buckets_log2 = new_size_log2;
|
||||
PR_DELETE(old_hash_buckets);
|
||||
|
||||
PR_LOG(_pr_cmon_lm, PR_LOG_NOTICE,
|
||||
("expanded monitor cache to %d (buckets %d)",
|
||||
num_free_entries, entries));
|
||||
|
||||
return PR_SUCCESS;
|
||||
} /* ExpandMonitorCache */
|
||||
|
||||
/*
|
||||
** Lookup a monitor cache entry by address. Return a pointer to the
|
||||
** pointer to the monitor cache entry on success, null on failure.
|
||||
*/
|
||||
static MonitorCacheEntry **LookupMonitorCacheEntry(void *address)
|
||||
{
|
||||
PRUintn hash;
|
||||
MonitorCacheEntry **pp, *p;
|
||||
|
||||
hash = HASH(address);
|
||||
pp = hash_buckets + hash;
|
||||
while ((p = *pp) != 0) {
|
||||
if (p->address == address) {
|
||||
if (p->cacheEntryCount > 0)
|
||||
return pp;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
pp = &p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to create a new cached monitor. If it's already in the cache,
|
||||
** great - return it. Otherwise get a new free cache entry and set it
|
||||
** up. If the cache free space is getting low, expand the cache.
|
||||
*/
|
||||
static PRMonitor *CreateMonitor(void *address)
|
||||
{
|
||||
PRUintn hash;
|
||||
MonitorCacheEntry **pp, *p;
|
||||
|
||||
hash = HASH(address);
|
||||
pp = hash_buckets + hash;
|
||||
while ((p = *pp) != 0) {
|
||||
if (p->address == address) goto gotit;
|
||||
|
||||
pp = &p->next;
|
||||
}
|
||||
|
||||
/* Expand the monitor cache if we have run out of free slots in the table */
|
||||
if (num_free_entries < FREE_THRESHOLD)
|
||||
{
|
||||
/* Expand monitor cache */
|
||||
|
||||
/*
|
||||
** This function is called with the lock held. So what's the 'expanding' ** boolean all about? Seems a bit redundant.
|
||||
*/
|
||||
if (!expanding)
|
||||
{
|
||||
PRStatus rv;
|
||||
|
||||
expanding = PR_TRUE;
|
||||
rv = ExpandMonitorCache(num_hash_buckets_log2 + 1);
|
||||
expanding = PR_FALSE;
|
||||
if (PR_FAILURE == rv) return NULL;
|
||||
|
||||
/* redo the hash because it'll be different now */
|
||||
hash = HASH(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
** We are in process of expanding and we need a cache
|
||||
** monitor. Make sure we have enough!
|
||||
*/
|
||||
PR_ASSERT(num_free_entries > 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a new monitor */ p = free_entries;
|
||||
free_entries = p->next;
|
||||
num_free_entries--;
|
||||
p->address = address;
|
||||
p->next = hash_buckets[hash];
|
||||
hash_buckets[hash] = p;
|
||||
PR_ASSERT(p->cacheEntryCount == 0);
|
||||
|
||||
gotit:
|
||||
p->cacheEntryCount++;
|
||||
return p->mon;
|
||||
}
|
||||
|
||||
/* this is needed by prinit for some reason */
|
||||
void
|
||||
_PR_InitCMon (void)
|
||||
{
|
||||
_PR_NEW_LOCK_MCACHE();
|
||||
ExpandMonitorCache(3);
|
||||
_pr_mcache_ready = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Like PR_EnterMonitor except use the "address" to find a monitor in the
|
||||
** monitor cache. If successful, returns the PRMonitor now associated
|
||||
** with "address". Note that you must PR_CExitMonitor the address to
|
||||
** release the monitor cache entry (otherwise the monitor cache will fill
|
||||
** up). This call will return NULL if the monitor cache needs to be
|
||||
** expanded and the system is out of memory.
|
||||
*/
|
||||
PR_IMPLEMENT(PRMonitor*)
|
||||
PR_CEnterMonitor (void *address)
|
||||
{
|
||||
PRMonitor *mon;
|
||||
|
||||
_PR_LOCK_MCACHE();
|
||||
mon = CreateMonitor( address );
|
||||
_PR_UNLOCK_MCACHE();
|
||||
|
||||
if( !mon ) return( NULL );
|
||||
|
||||
PR_EnterMonitor( mon );
|
||||
return( mon );
|
||||
}
|
||||
|
||||
/*
|
||||
** Like PR_ExitMonitor except use the "address" to find a monitor in the
|
||||
** monitor cache.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_CExitMonitor (void *address)
|
||||
{
|
||||
MonitorCacheEntry **pp, *p;
|
||||
PRStatus status = PR_SUCCESS;
|
||||
|
||||
_PR_LOCK_MCACHE();
|
||||
pp = LookupMonitorCacheEntry(address);
|
||||
if (pp != NULL) {
|
||||
p = *pp;
|
||||
if (--p->cacheEntryCount == 0) {
|
||||
/*
|
||||
** Nobody is using the system monitor. Put it on the cached free
|
||||
** list. We are safe from somebody trying to use it because we
|
||||
** have the mcache locked.
|
||||
*/
|
||||
p->address = 0; /* defensive move */
|
||||
*pp = p->next; /* unlink from hash_buckets */
|
||||
p->next = free_entries; /* link into free list */
|
||||
free_entries = p;
|
||||
num_free_entries++; /* count it as free */
|
||||
}
|
||||
status = PR_ExitMonitor(p->mon);
|
||||
} else {
|
||||
status = PR_FAILURE;
|
||||
}
|
||||
_PR_UNLOCK_MCACHE();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
** Like PR_Wait except use the "address" to find a monitor in the
|
||||
** monitor cache.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_CWait (void *address, PRIntervalTime timeout)
|
||||
{
|
||||
MonitorCacheEntry **pp;
|
||||
PRMonitor *mon;
|
||||
|
||||
_PR_LOCK_MCACHE();
|
||||
pp = LookupMonitorCacheEntry(address);
|
||||
mon = pp ? ((*pp)->mon) : NULL;
|
||||
_PR_UNLOCK_MCACHE();
|
||||
|
||||
if (mon == NULL)
|
||||
return PR_FAILURE;
|
||||
else
|
||||
{
|
||||
return PR_Wait( mon, timeout );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Like PR_Notify except use the "address" to find a monitor in the
|
||||
** monitor cache.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_CNotify (void *address)
|
||||
{
|
||||
MonitorCacheEntry **pp;
|
||||
PRMonitor *mon;
|
||||
|
||||
_PR_LOCK_MCACHE();
|
||||
pp = LookupMonitorCacheEntry(address);
|
||||
mon = pp ? ((*pp)->mon) : NULL;
|
||||
_PR_UNLOCK_MCACHE();
|
||||
|
||||
if (mon == NULL)
|
||||
return PR_FAILURE;
|
||||
else
|
||||
{
|
||||
return PR_Notify(mon);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Like PR_NotifyAll except use the "address" to find a monitor in the
|
||||
** monitor cache.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_CNotifyAll (void *address)
|
||||
{
|
||||
MonitorCacheEntry **pp;
|
||||
PRMonitor *mon;
|
||||
|
||||
_PR_LOCK_MCACHE();
|
||||
pp = LookupMonitorCacheEntry(address);
|
||||
mon = pp ? ((*pp)->mon) : NULL;
|
||||
_PR_UNLOCK_MCACHE();
|
||||
|
||||
if (mon == NULL)
|
||||
return PR_FAILURE;
|
||||
else
|
||||
{
|
||||
return PR_NotifyAll(mon);
|
||||
}
|
||||
}
|
||||
161
mozilla/nsprpub/pr/src/bthreads/btcvar.c
Normal file
161
mozilla/nsprpub/pr/src/bthreads/btcvar.c
Normal file
@ -0,0 +1,161 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include <kernel/OS.h>
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
/*
|
||||
** Create a new condition variable.
|
||||
**
|
||||
** "lock" is the lock used to protect the condition variable.
|
||||
**
|
||||
** Condition variables are synchronization objects that threads can use
|
||||
** to wait for some condition to occur.
|
||||
**
|
||||
** This may fail if memory is tight or if some operating system resource
|
||||
** is low. In such cases, a NULL will be returned.
|
||||
*/
|
||||
PR_IMPLEMENT(PRCondVar*)
|
||||
PR_NewCondVar (PRLock *lock)
|
||||
{
|
||||
PRCondVar *cv = PR_NEW( PRCondVar );
|
||||
PR_ASSERT( NULL != lock );
|
||||
if( NULL != cv )
|
||||
{
|
||||
cv->lock = lock;
|
||||
PR_ASSERT((cv->isem = create_sem( 1, "nspr_sem")) >= B_NO_ERROR );
|
||||
}
|
||||
return cv;
|
||||
} /* PR_NewCondVar */
|
||||
|
||||
/*
|
||||
** Destroy a condition variable. There must be no thread
|
||||
** waiting on the condvar. The caller is responsible for guaranteeing
|
||||
** that the condvar is no longer in use.
|
||||
**
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
PR_DestroyCondVar (PRCondVar *cvar)
|
||||
{
|
||||
PR_ASSERT( delete_sem( cvar->isem ) == B_NO_ERROR );
|
||||
PR_DELETE( cvar );
|
||||
}
|
||||
|
||||
/*
|
||||
** The thread that waits on a condition is blocked in a "waiting on
|
||||
** condition" state until another thread notifies the condition or a
|
||||
** caller specified amount of time expires. The lock associated with
|
||||
** the condition variable will be released, which must have be held
|
||||
** prior to the call to wait.
|
||||
**
|
||||
** Logically a notified thread is moved from the "waiting on condition"
|
||||
** state and made "ready." When scheduled, it will attempt to reacquire
|
||||
** the lock that it held when wait was called.
|
||||
**
|
||||
** The timeout has two well known values, PR_INTERVAL_NO_TIMEOUT and
|
||||
** PR_INTERVAL_NO_WAIT. The former value requires that a condition be
|
||||
** notified (or the thread interrupted) before it will resume from the
|
||||
** wait. If the timeout has a value of PR_INTERVAL_NO_WAIT, the effect
|
||||
** is to release the lock, possibly causing a rescheduling within the
|
||||
** runtime, then immediately attempting to reacquire the lock and resume.
|
||||
**
|
||||
** Any other value for timeout will cause the thread to be rescheduled
|
||||
** either due to explicit notification or an expired interval. The latter
|
||||
** must be determined by treating time as one part of the monitored data
|
||||
** being protected by the lock and tested explicitly for an expired
|
||||
** interval.
|
||||
**
|
||||
** Returns PR_FAILURE if the caller has not locked the lock associated
|
||||
** with the condition variable or the thread was interrupted (PR_Interrupt()).
|
||||
** The particular reason can be extracted with PR_GetError().
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_WaitCondVar (PRCondVar *cvar, PRIntervalTime timeout)
|
||||
{
|
||||
status_t result;
|
||||
|
||||
/*
|
||||
** This is an entirely stupid bug, but... If you call
|
||||
** acquire_sem_etc with a timeout of exactly 1,000,000 microseconds
|
||||
** it returns immediately with B_NO_ERROR. 1,000,010 microseconds
|
||||
** returns as expected. Running BeOS/Intel R3.1 at this time.
|
||||
** Forwarded to Be, Inc. for resolution, Bug ID 980624-225956
|
||||
**
|
||||
** Update: Be couldn't reproduce it, but removing timeout++ still
|
||||
** exhibits the problem on BeOS/Intel R4 and BeOS/PPC R4.
|
||||
*/
|
||||
|
||||
timeout++;
|
||||
|
||||
PR_Unlock( cvar->lock );
|
||||
|
||||
if( PR_INTERVAL_NO_WAIT != timeout )
|
||||
{
|
||||
if( PR_INTERVAL_NO_TIMEOUT == timeout )
|
||||
{
|
||||
if( acquire_sem( cvar->isem ) != B_NO_ERROR ) return PR_FAILURE;
|
||||
|
||||
} else
|
||||
{
|
||||
result = acquire_sem_etc( cvar->isem, 1, B_TIMEOUT, PR_IntervalToMicroseconds( timeout ) );
|
||||
if( result != B_NO_ERROR && result != B_TIMED_OUT )
|
||||
return PR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
PR_Lock( cvar->lock );
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
** Notify ONE thread that is currently waiting on 'cvar'. Which thread is
|
||||
** dependent on the implementation of the runtime. Common sense would dictate
|
||||
** that all threads waiting on a single condition have identical semantics,
|
||||
** therefore which one gets notified is not significant.
|
||||
**
|
||||
** The calling thead must hold the lock that protects the condition, as
|
||||
** well as the invariants that are tightly bound to the condition, when
|
||||
** notify is called.
|
||||
**
|
||||
** Returns PR_FAILURE if the caller has not locked the lock associated
|
||||
** with the condition variable.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_NotifyCondVar (PRCondVar *cvar)
|
||||
{
|
||||
if( release_sem( cvar->isem ) != B_NO_ERROR ) return PR_FAILURE;
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
** Notify all of the threads waiting on the condition variable. The order
|
||||
** that the threads are notified is indeterminant. The lock that protects
|
||||
** the condition must be held.
|
||||
**
|
||||
** Returns PR_FAILURE if the caller has not locked the lock associated
|
||||
** with the condition variable.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_NotifyAllCondVar (PRCondVar *cvar)
|
||||
{
|
||||
sem_info semInfo;
|
||||
|
||||
if( get_sem_info( cvar->isem, &semInfo ) != B_NO_ERROR )
|
||||
return PR_FAILURE;
|
||||
|
||||
if( release_sem_etc( cvar->isem, semInfo.count, 0 ) != B_NO_ERROR )
|
||||
return PR_FAILURE;
|
||||
}
|
||||
89
mozilla/nsprpub/pr/src/bthreads/btlocks.c
Normal file
89
mozilla/nsprpub/pr/src/bthreads/btlocks.c
Normal file
@ -0,0 +1,89 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
** File: btlocks.c
|
||||
** Description: Implemenation for thread locks using bthreads
|
||||
** Exports: prlock.h
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
void
|
||||
_PR_InitLocks (void)
|
||||
{
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRLock*)
|
||||
PR_NewLock (void)
|
||||
{
|
||||
PRLock *lock;
|
||||
status_t semresult;
|
||||
|
||||
if (!_pr_initialized) _PR_ImplicitInitialization();
|
||||
|
||||
lock = PR_NEWZAP(PRLock);
|
||||
if (lock != NULL) {
|
||||
|
||||
lock->benaphoreCount = 0;
|
||||
lock->semaphoreID = create_sem( 0, "nsprLockSem" );
|
||||
if( lock->semaphoreID < B_NO_ERROR ) {
|
||||
|
||||
PR_DELETE( lock );
|
||||
lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PR_DestroyLock (PRLock* lock)
|
||||
{
|
||||
PR_ASSERT(NULL != lock);
|
||||
PR_ASSERT(delete_sem(lock->semaphoreID) == B_NO_ERROR);
|
||||
PR_DELETE(lock);
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PR_Lock (PRLock* lock)
|
||||
{
|
||||
PR_ASSERT(lock != NULL);
|
||||
|
||||
if( atomic_add( &lock->benaphoreCount, 1 ) > 0 ) {
|
||||
|
||||
if( acquire_sem(lock->semaphoreID ) != B_NO_ERROR ) {
|
||||
|
||||
atomic_add( &lock->benaphoreCount, -1 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lock->owner = find_thread( NULL );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_Unlock (PRLock* lock)
|
||||
{
|
||||
PR_ASSERT(lock != NULL);
|
||||
lock->owner = NULL;
|
||||
if( atomic_add( &lock->benaphoreCount, -1 ) > 1 ) {
|
||||
|
||||
release_sem( lock->semaphoreID );
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
80
mozilla/nsprpub/pr/src/bthreads/btmisc.c
Normal file
80
mozilla/nsprpub/pr/src/bthreads/btmisc.c
Normal file
@ -0,0 +1,80 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")}
|
||||
// void _MD_StartInterrupts(void) {PT_LOG("_MD_StartInterrupts")}
|
||||
|
||||
/* this is a total hack.. */
|
||||
|
||||
struct protoent* getprotobyname(const char* name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct protoent* getprotobynumber(int number)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this is needed by prinit for some reason */
|
||||
void
|
||||
_PR_InitStacks (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* this is needed by prinit for some reason */
|
||||
void
|
||||
_PR_InitTPD (void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
** Create extra virtual processor threads. Generally used with MP systems.
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
PR_SetConcurrency (PRUintn numCPUs)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
** Set thread recycle mode to on (1) or off (0)
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
PR_SetThreadRecycleMode (PRUint32 flag)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
** Get context registers, return with error for now.
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(PRWord *)
|
||||
_MD_HomeGCRegisters( PRThread *t, int isCurrent, int *np )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void *)
|
||||
PR_GetSP( PRThread *t )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_EnumerateThreads( PREnumerator func, void *arg )
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
192
mozilla/nsprpub/pr/src/bthreads/btmon.c
Normal file
192
mozilla/nsprpub/pr/src/bthreads/btmon.c
Normal file
@ -0,0 +1,192 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include <kernel/OS.h>
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
/*
|
||||
** Create a new monitor. Monitors are re-entrant locks with a single built-in
|
||||
** condition variable.
|
||||
**
|
||||
** This may fail if memory is tight or if some operating system resource
|
||||
** is low.
|
||||
*/
|
||||
PR_IMPLEMENT(PRMonitor*)
|
||||
PR_NewMonitor (void)
|
||||
{
|
||||
PRMonitor *mon;
|
||||
PRCondVar *cvar;
|
||||
PRLock *lock;
|
||||
|
||||
mon = PR_NEWZAP( PRMonitor );
|
||||
if( mon )
|
||||
{
|
||||
lock = PR_NewLock();
|
||||
if( !lock )
|
||||
{
|
||||
PR_DELETE( mon );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
cvar = PR_NewCondVar( lock );
|
||||
if( !cvar )
|
||||
{
|
||||
PR_DestroyLock( lock );
|
||||
PR_DELETE( mon );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
mon->cvar = cvar;
|
||||
mon->name = NULL;
|
||||
}
|
||||
|
||||
return( mon );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
|
||||
{
|
||||
PRMonitor* mon = PR_NewMonitor();
|
||||
mon->name = name;
|
||||
return mon;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy a monitor. The caller is responsible for guaranteeing that the
|
||||
** monitor is no longer in use. There must be no thread waiting on the
|
||||
** monitor's condition variable and that the lock is not held.
|
||||
**
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
PR_DestroyMonitor (PRMonitor *mon)
|
||||
{
|
||||
PR_DestroyLock( mon->cvar->lock );
|
||||
PR_DestroyCondVar( mon->cvar );
|
||||
PR_DELETE( mon );
|
||||
}
|
||||
|
||||
/*
|
||||
** Enter the lock associated with the monitor. If the calling thread currently
|
||||
** is in the monitor, the call to enter will silently succeed. In either case,
|
||||
** it will increment the entry count by one.
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
PR_EnterMonitor (PRMonitor *mon)
|
||||
{
|
||||
if( mon->cvar->lock->owner == find_thread( NULL ) )
|
||||
{
|
||||
mon->entryCount++;
|
||||
|
||||
} else
|
||||
{
|
||||
PR_Lock( mon->cvar->lock );
|
||||
mon->entryCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Decrement the entry count associated with the monitor. If the decremented
|
||||
** entry count is zero, the monitor is exited. Returns PR_FAILURE if the
|
||||
** calling thread has not entered the monitor.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_ExitMonitor (PRMonitor *mon)
|
||||
{
|
||||
if( mon->cvar->lock->owner != find_thread( NULL ) )
|
||||
{
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
if( --mon->entryCount == 0 )
|
||||
{
|
||||
return( PR_Unlock( mon->cvar->lock ) );
|
||||
}
|
||||
return( PR_SUCCESS );
|
||||
}
|
||||
|
||||
/*
|
||||
** Wait for a notify on the monitor's condition variable. Sleep for "ticks"
|
||||
** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is
|
||||
** indefinite).
|
||||
**
|
||||
** While the thread is waiting it exits the monitor (as if it called
|
||||
** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When
|
||||
** the wait has finished the thread regains control of the monitors lock
|
||||
** with the same entry count as before the wait began.
|
||||
**
|
||||
** The thread waiting on the monitor will be resumed when the monitor is
|
||||
** notified (assuming the thread is the next in line to receive the
|
||||
** notify) or when the "ticks" timeout elapses.
|
||||
**
|
||||
** Returns PR_FAILURE if the caller has not entered the monitor.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_Wait (PRMonitor *mon, PRIntervalTime ticks)
|
||||
{
|
||||
PRUint32 entryCount;
|
||||
PRUintn status;
|
||||
PRThread *meThread;
|
||||
thread_id me = find_thread( NULL );
|
||||
meThread = PR_GetCurrentThread();
|
||||
|
||||
if( mon->cvar->lock->owner != me ) return( PR_FAILURE );
|
||||
|
||||
entryCount = mon->entryCount;
|
||||
mon->entryCount = 0;
|
||||
|
||||
status = PR_WaitCondVar( mon->cvar, ticks );
|
||||
|
||||
mon->entryCount = entryCount;
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
/*
|
||||
** Notify a thread waiting on the monitor's condition variable. If a thread
|
||||
** is waiting on the condition variable (using PR_Wait) then it is awakened
|
||||
** and attempts to reenter the monitor.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_Notify (PRMonitor *mon)
|
||||
{
|
||||
if( mon->cvar->lock->owner != find_thread( NULL ) )
|
||||
{
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
|
||||
PR_NotifyCondVar( mon->cvar );
|
||||
return( PR_SUCCESS );
|
||||
}
|
||||
|
||||
/*
|
||||
** Notify all of the threads waiting on the monitor's condition variable.
|
||||
** All of threads waiting on the condition are scheduled to reenter the
|
||||
** monitor.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_NotifyAll (PRMonitor *mon)
|
||||
{
|
||||
if( mon->cvar->lock->owner != find_thread( NULL ) )
|
||||
{
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
|
||||
PR_NotifyAllCondVar( mon->cvar );
|
||||
return( PR_SUCCESS );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRIntn)
|
||||
PR_GetMonitorEntryCount(PRMonitor *mon)
|
||||
{
|
||||
return( mon->entryCount );
|
||||
}
|
||||
|
||||
100
mozilla/nsprpub/pr/src/bthreads/btsem.c
Normal file
100
mozilla/nsprpub/pr/src/bthreads/btsem.c
Normal file
@ -0,0 +1,100 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include <kernel/OS.h>
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
/*
|
||||
** Create a new semaphore object.
|
||||
*/
|
||||
PR_IMPLEMENT(PRSemaphore*)
|
||||
PR_NewSem (PRUintn value)
|
||||
{
|
||||
PRSemaphore *semaphore;
|
||||
|
||||
if (!_pr_initialized) _PR_ImplicitInitialization();
|
||||
|
||||
semaphore = PR_NEWZAP(PRSemaphore);
|
||||
if (NULL != semaphore) {
|
||||
if ((semaphore->sem = create_sem(value, "nspr_sem")) < B_NO_ERROR)
|
||||
return NULL;
|
||||
else
|
||||
return semaphore;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy the given semaphore object.
|
||||
**
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
PR_DestroySem (PRSemaphore *sem)
|
||||
{
|
||||
PR_ASSERT(sem != NULL);
|
||||
PR_ASSERT(delete_sem(sem->sem) == B_NO_ERROR);
|
||||
PR_DELETE(sem);
|
||||
}
|
||||
|
||||
/*
|
||||
** Wait on a Semaphore.
|
||||
**
|
||||
** This routine allows a calling thread to wait or proceed depending upon
|
||||
** the state of the semahore sem. The thread can proceed only if the
|
||||
** counter value of the semaphore sem is currently greater than 0. If the
|
||||
** value of semaphore sem is positive, it is decremented by one and the
|
||||
** routine returns immediately allowing the calling thread to continue. If
|
||||
** the value of semaphore sem is 0, the calling thread blocks awaiting the
|
||||
** semaphore to be released by another thread.
|
||||
**
|
||||
** This routine can return PR_PENDING_INTERRUPT if the waiting thread
|
||||
** has been interrupted.
|
||||
*/
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_WaitSem (PRSemaphore *sem)
|
||||
{
|
||||
PR_ASSERT(sem != NULL);
|
||||
if (acquire_sem(sem->sem) == B_NO_ERROR)
|
||||
return PR_SUCCESS;
|
||||
else
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine increments the counter value of the semaphore. If other
|
||||
** threads are blocked for the semaphore, then the scheduler will
|
||||
** determine which ONE thread will be unblocked.
|
||||
*/
|
||||
PR_IMPLEMENT(void)
|
||||
PR_PostSem (PRSemaphore *sem)
|
||||
{
|
||||
PR_ASSERT(sem != NULL);
|
||||
PR_ASSERT(release_sem(sem->sem) == B_NO_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
** Returns the value of the semaphore referenced by sem without affecting
|
||||
** the state of the semaphore. The value represents the semaphore value
|
||||
** at the time of the call, but may not be the actual value when the
|
||||
** caller inspects it.
|
||||
*/
|
||||
PR_IMPLEMENT(PRUintn)
|
||||
PR_GetValueSem (PRSemaphore *sem)
|
||||
{
|
||||
sem_info info;
|
||||
|
||||
PR_ASSERT(sem != NULL);
|
||||
get_sem_info(sem->sem, &info);
|
||||
return info.count;
|
||||
}
|
||||
780
mozilla/nsprpub/pr/src/bthreads/btthread.c
Normal file
780
mozilla/nsprpub/pr/src/bthreads/btthread.c
Normal file
@ -0,0 +1,780 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include <kernel/OS.h>
|
||||
|
||||
#include "prlog.h"
|
||||
#include "primpl.h"
|
||||
#include "prcvar.h"
|
||||
#include "prpdce.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define BT_THREAD_PRIMORD 0x01 /* this is the primordial thread */
|
||||
#define BT_THREAD_SYSTEM 0x02 /* this is a system thread */
|
||||
|
||||
struct _BT_Bookeeping
|
||||
{
|
||||
PRLock *ml; /* a lock to protect ourselves */
|
||||
PRCondVar *cv; /* used to signal global things */
|
||||
PRInt32 threadCount; /* user thred count */
|
||||
|
||||
} bt_book = { 0 };
|
||||
|
||||
/*
|
||||
** A structure at the root of the thread private data. Each member of
|
||||
** the array keys[] points to a hash table based on the thread's ID.
|
||||
*/
|
||||
|
||||
struct _BT_PrivateData
|
||||
{
|
||||
PRLock *lock; /* A lock to coordinate access */
|
||||
struct _BT_PrivateHash *keys[128]; /* Up to 128 keys, pointing to a hash table */
|
||||
|
||||
} bt_privateRoot = { 0 };
|
||||
|
||||
/*
|
||||
** A dynamically allocated structure that contains 256 hash buckets that
|
||||
** contain a linked list of thread IDs. The hash is simply the last 8 bits
|
||||
** of the thread_id. ( current thread_id & 0x000000FF )
|
||||
*/
|
||||
|
||||
struct _BT_PrivateHash
|
||||
{
|
||||
void (PR_CALLBACK *destructor)(void *arg); /* The destructor */
|
||||
struct _BT_PrivateEntry *next[256]; /* Pointer to the first element in the list */
|
||||
};
|
||||
|
||||
/*
|
||||
** A dynamically allocated structure that is a member of a linked list of
|
||||
** thread IDs.
|
||||
*/
|
||||
|
||||
struct _BT_PrivateEntry
|
||||
{
|
||||
struct _BT_PrivateEntry *next; /* Pointer to the next thread */
|
||||
thread_id threadID; /* The BeOS thread ID */
|
||||
void *data; /* The data */
|
||||
};
|
||||
|
||||
PRUint32 _bt_mapPriority( PRThreadPriority priority );
|
||||
PR_IMPLEMENT(void *) _bt_getThreadPrivate(PRUintn index);
|
||||
|
||||
void
|
||||
_PR_InitThreads (PRThreadType type, PRThreadPriority priority,
|
||||
PRUintn maxPTDs)
|
||||
{
|
||||
PRThread *primordialThread;
|
||||
PRLock *tempLock;
|
||||
PRUintn tempKey;
|
||||
PRUint32 beThreadPriority;
|
||||
|
||||
/*
|
||||
** Create a NSPR structure for our primordial thread.
|
||||
*/
|
||||
|
||||
primordialThread = PR_NEWZAP(PRThread);
|
||||
if( NULL == primordialThread )
|
||||
{
|
||||
PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the priority to the desired level.
|
||||
*/
|
||||
|
||||
beThreadPriority = _bt_mapPriority( priority );
|
||||
|
||||
set_thread_priority( find_thread( NULL ), beThreadPriority );
|
||||
|
||||
primordialThread->state |= BT_THREAD_PRIMORD;
|
||||
primordialThread->priority = priority;
|
||||
|
||||
/*
|
||||
** Initialize the thread tracking data structures
|
||||
*/
|
||||
|
||||
bt_privateRoot.lock = PR_NewLock();
|
||||
if( NULL == bt_privateRoot.lock )
|
||||
{
|
||||
PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Grab a key. We're guaranteed to be key #0, since we are
|
||||
** always the first one in.
|
||||
*/
|
||||
|
||||
if( PR_NewThreadPrivateIndex( &tempKey, NULL ) != PR_SUCCESS )
|
||||
{
|
||||
PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
PR_ASSERT( tempKey == 0 );
|
||||
|
||||
/*
|
||||
** Stuff our new PRThread structure into our thread specific
|
||||
** slot.
|
||||
*/
|
||||
|
||||
if( PR_SetThreadPrivate( (PRUint8) 0, (void *) primordialThread ) == PR_FAILURE )
|
||||
{
|
||||
PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate some memory to hold our global lock. We never clean it
|
||||
** up later, but BeOS automatically frees memory when the thread
|
||||
** dies.
|
||||
*/
|
||||
|
||||
bt_book.ml = PR_NewLock();
|
||||
if( NULL == bt_book.ml )
|
||||
{
|
||||
PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
tempLock = PR_NewLock();
|
||||
if( NULL == tempLock )
|
||||
{
|
||||
PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
bt_book.cv = PR_NewCondVar( tempLock );
|
||||
if( NULL == bt_book.cv )
|
||||
{
|
||||
PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32
|
||||
_bt_mapPriority( PRThreadPriority priority )
|
||||
{
|
||||
switch( priority )
|
||||
{
|
||||
case PR_PRIORITY_LOW: return( B_LOW_PRIORITY );
|
||||
case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY );
|
||||
case PR_PRIORITY_HIGH: return( B_DISPLAY_PRIORITY );
|
||||
case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY );
|
||||
default: return( B_NORMAL_PRIORITY );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper that all threads invoke that allows us to set some
|
||||
* things up prior to a thread's invocation and clean up after a thread has
|
||||
* exited.
|
||||
*/
|
||||
static void*
|
||||
_bt_root (void* arg)
|
||||
{
|
||||
PRThread *thred = (PRThread*)arg;
|
||||
PRIntn rv;
|
||||
void *privData;
|
||||
status_t result;
|
||||
int i;
|
||||
|
||||
struct _BT_PrivateHash *hashTable;
|
||||
|
||||
/* Set within the current thread the pointer to our object. This
|
||||
object will be deleted when the thread termintates. */
|
||||
|
||||
PR_ASSERT( PR_SetThreadPrivate( 0, (void *) thred ) == PR_SUCCESS );
|
||||
|
||||
thred->startFunc(thred->arg); /* run the dang thing */
|
||||
|
||||
/*
|
||||
** Call the destructor, if available.
|
||||
*/
|
||||
|
||||
PR_Lock( bt_privateRoot.lock );
|
||||
|
||||
for( i = 0; i < 128; i++ )
|
||||
{
|
||||
hashTable = bt_privateRoot.keys[i];
|
||||
|
||||
if( hashTable != NULL )
|
||||
{
|
||||
if( hashTable->destructor != NULL )
|
||||
{
|
||||
privData = _bt_getThreadPrivate( i );
|
||||
|
||||
if( privData != NULL )
|
||||
{
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
hashTable->destructor( privData );
|
||||
PR_Lock( bt_privateRoot.lock );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
|
||||
/* decrement our thread counters */
|
||||
|
||||
PR_Lock( bt_book.ml );
|
||||
|
||||
if (thred->state & BT_THREAD_SYSTEM) {
|
||||
#if 0
|
||||
bt_book.system -= 1;
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
bt_book.threadCount--;
|
||||
|
||||
if( 0 == bt_book.threadCount )
|
||||
{
|
||||
PR_NotifyAllCondVar(bt_book.cv);
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock( bt_book.ml );
|
||||
|
||||
if( thred->md.is_joinable == 1 )
|
||||
{
|
||||
/*
|
||||
** This is a joinable thread. Keep suspending
|
||||
** until is_joining is set to 1
|
||||
*/
|
||||
|
||||
if( thred->md.is_joining == 0 )
|
||||
{
|
||||
suspend_thread( thred->md.tid );
|
||||
}
|
||||
}
|
||||
|
||||
/* delete the thread object */
|
||||
PR_DELETE(thred);
|
||||
|
||||
PR_ASSERT( PR_SetThreadPrivate( (PRUint8) 0, (void *) NULL ) == PR_SUCCESS );
|
||||
exit_thread( NULL );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRThread*)
|
||||
PR_CreateThread (PRThreadType type, void (*start)(void* arg), void* arg,
|
||||
PRThreadPriority priority, PRThreadScope scope,
|
||||
PRThreadState state, PRUint32 stackSize)
|
||||
{
|
||||
PRUint32 bePriority;
|
||||
|
||||
PRThread* thred = PR_NEWZAP(PRThread);
|
||||
|
||||
if (!_pr_initialized) _PR_ImplicitInitialization();
|
||||
|
||||
if (thred != NULL) {
|
||||
thred->arg = arg;
|
||||
thred->startFunc = start;
|
||||
thred->priority = priority;
|
||||
|
||||
if( state == PR_JOINABLE_THREAD )
|
||||
{
|
||||
thred->md.is_joinable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
thred->md.is_joinable = 0;
|
||||
}
|
||||
|
||||
thred->md.is_joining = 0;
|
||||
|
||||
/* keep some books */
|
||||
|
||||
PR_Lock( bt_book.ml );
|
||||
|
||||
if (PR_SYSTEM_THREAD == type) {
|
||||
thred->state |= BT_THREAD_SYSTEM;
|
||||
#if 0
|
||||
bt_book.system += 1;
|
||||
#endif
|
||||
} else {
|
||||
bt_book.threadCount++;
|
||||
}
|
||||
|
||||
PR_Unlock( bt_book.ml );
|
||||
|
||||
bePriority = _bt_mapPriority( priority );
|
||||
|
||||
thred->md.tid = spawn_thread((thread_func)_bt_root, "moz-thread",
|
||||
bePriority, thred);
|
||||
if (thred->md.tid < B_OK) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, thred->md.tid);
|
||||
PR_DELETE(thred);
|
||||
thred = NULL;
|
||||
}
|
||||
|
||||
if (resume_thread(thred->md.tid) < B_OK) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 0);
|
||||
PR_DELETE(thred);
|
||||
thred = NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
}
|
||||
|
||||
return thred;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_JoinThread (PRThread* thred)
|
||||
{
|
||||
status_t eval, status;
|
||||
|
||||
PR_ASSERT(thred != NULL);
|
||||
|
||||
if( thred->md.is_joinable != 1 )
|
||||
{
|
||||
PR_SetError( PR_UNKNOWN_ERROR, 0 );
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
|
||||
thred->md.is_joining = 1;
|
||||
|
||||
status = wait_for_thread(thred->md.tid, &eval);
|
||||
|
||||
if (status < B_NO_ERROR) {
|
||||
|
||||
PR_SetError(PR_UNKNOWN_ERROR, status);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRThread*)
|
||||
PR_GetCurrentThread ()
|
||||
{
|
||||
void* thred;
|
||||
|
||||
if (!_pr_initialized) _PR_ImplicitInitialization();
|
||||
|
||||
thred = PR_GetThreadPrivate( (PRUint8) 0 );
|
||||
PR_ASSERT(NULL != thred);
|
||||
|
||||
return (PRThread*)thred;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRThreadScope)
|
||||
PR_GetThreadScope (const PRThread* thred)
|
||||
{
|
||||
PR_ASSERT(thred != NULL);
|
||||
return PR_GLOBAL_THREAD;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRThreadType)
|
||||
PR_GetThreadType (const PRThread* thred)
|
||||
{
|
||||
PR_ASSERT(thred != NULL);
|
||||
return (thred->state & BT_THREAD_SYSTEM) ?
|
||||
PR_SYSTEM_THREAD : PR_USER_THREAD;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRThreadState)
|
||||
PR_GetThreadState (const PRThread* thred)
|
||||
{
|
||||
PR_ASSERT(thred != NULL);
|
||||
return PR_JOINABLE_THREAD;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRThreadPriority)
|
||||
PR_GetThreadPriority (const PRThread* thred)
|
||||
{
|
||||
PR_ASSERT(thred != NULL);
|
||||
return thred->priority;
|
||||
} /* PR_GetThreadPriority */
|
||||
|
||||
PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred,
|
||||
PRThreadPriority newPri)
|
||||
{
|
||||
PRUint32 bePriority;
|
||||
|
||||
PR_ASSERT( thred != NULL );
|
||||
|
||||
thred->priority = newPri;
|
||||
bePriority = _bt_mapPriority( newPri );
|
||||
set_thread_priority( thred->md.tid, bePriority );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_NewThreadPrivateIndex (PRUintn* newIndex,
|
||||
PRThreadPrivateDTOR destructor)
|
||||
{
|
||||
PRUintn index;
|
||||
struct _BT_PrivateHash *tempPointer;
|
||||
|
||||
if (!_pr_initialized) _PR_ImplicitInitialization();
|
||||
|
||||
/*
|
||||
** Grab the lock, or hang until it is free. This is critical code,
|
||||
** and only one thread at a time should be going through it.
|
||||
*/
|
||||
|
||||
PR_Lock( bt_privateRoot.lock );
|
||||
|
||||
/*
|
||||
** Run through the array of keys, find the first one that's zero.
|
||||
** Exit if we hit the top of the array.
|
||||
*/
|
||||
|
||||
index = 0;
|
||||
|
||||
while( bt_privateRoot.keys[index] != 0 )
|
||||
{
|
||||
index++;
|
||||
|
||||
if( 128 == index )
|
||||
{
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Index has the first available zeroed slot. Allocate a
|
||||
** _BT_PrivateHash structure, all zeroed. Assuming that goes
|
||||
** well, return the index.
|
||||
*/
|
||||
|
||||
tempPointer = PR_NEWZAP( struct _BT_PrivateHash );
|
||||
|
||||
if( 0 == tempPointer ) {
|
||||
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
|
||||
bt_privateRoot.keys[index] = tempPointer;
|
||||
tempPointer->destructor = destructor;
|
||||
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
|
||||
*newIndex = index;
|
||||
|
||||
return( PR_SUCCESS );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_SetThreadPrivate (PRUintn index, void* priv)
|
||||
{
|
||||
thread_id currentThread;
|
||||
PRUint8 hashBucket;
|
||||
void *tempPointer;
|
||||
|
||||
struct _BT_PrivateHash *hashTable;
|
||||
struct _BT_PrivateEntry *currentEntry;
|
||||
struct _BT_PrivateEntry *previousEntry;
|
||||
|
||||
/*
|
||||
** Sanity checking
|
||||
*/
|
||||
|
||||
if( index < 0 || index > 127 ) return( PR_FAILURE );
|
||||
|
||||
/*
|
||||
** Grab the thread ID for this thread. Assign it to a hash bucket.
|
||||
*/
|
||||
|
||||
currentThread = find_thread( NULL );
|
||||
hashBucket = currentThread & 0x000000FF;
|
||||
|
||||
/*
|
||||
** Lock out all other threads then grab the proper hash table based
|
||||
** on the passed index.
|
||||
*/
|
||||
|
||||
PR_Lock( bt_privateRoot.lock );
|
||||
|
||||
hashTable = bt_privateRoot.keys[index];
|
||||
|
||||
if( 0 == hashTable )
|
||||
{
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
|
||||
/*
|
||||
** Search through the linked list the end is reached or an existing
|
||||
** entry is found.
|
||||
*/
|
||||
|
||||
currentEntry = hashTable->next[ hashBucket ];
|
||||
previousEntry = NULL;
|
||||
|
||||
while( currentEntry != 0 )
|
||||
{
|
||||
if( currentEntry->threadID == currentThread )
|
||||
{
|
||||
/*
|
||||
** Found a structure previously created for this thread.
|
||||
** Is there a destructor to be called?
|
||||
*/
|
||||
|
||||
if( hashTable->destructor != NULL )
|
||||
{
|
||||
if( currentEntry->data != NULL )
|
||||
{
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
hashTable->destructor( currentEntry->data );
|
||||
PR_Lock( bt_privateRoot.lock );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If the data was not NULL, and there was a destructor,
|
||||
** it has already been called. Overwrite the existing
|
||||
** data and return with success.
|
||||
*/
|
||||
|
||||
currentEntry->data = priv;
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
return( PR_SUCCESS );
|
||||
}
|
||||
|
||||
previousEntry = currentEntry;
|
||||
currentEntry = previousEntry->next;
|
||||
}
|
||||
|
||||
/*
|
||||
** If we're here, we didn't find an entry for this thread. Create
|
||||
** one and attach it to the end of the list.
|
||||
*/
|
||||
|
||||
currentEntry = PR_NEWZAP( struct _BT_PrivateEntry );
|
||||
|
||||
if( 0 == currentEntry )
|
||||
{
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
|
||||
currentEntry->threadID = currentThread;
|
||||
currentEntry->data = priv;
|
||||
|
||||
if( 0 == previousEntry )
|
||||
{
|
||||
/*
|
||||
** This is a special case. This is the first entry in the list
|
||||
** so set the hash table to point to this entry.
|
||||
*/
|
||||
|
||||
hashTable->next[ hashBucket ] = currentEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
previousEntry->next = currentEntry;
|
||||
}
|
||||
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
|
||||
return( PR_SUCCESS );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void*)
|
||||
_bt_getThreadPrivate(PRUintn index)
|
||||
{
|
||||
thread_id currentThread;
|
||||
PRUint8 hashBucket;
|
||||
void *tempPointer;
|
||||
|
||||
struct _BT_PrivateHash *hashTable;
|
||||
struct _BT_PrivateEntry *currentEntry;
|
||||
|
||||
/*
|
||||
** Sanity checking
|
||||
*/
|
||||
|
||||
if( index < 0 || index > 127 ) return( NULL );
|
||||
|
||||
/*
|
||||
** Grab the thread ID for this thread. Assign it to a hash bucket.
|
||||
*/
|
||||
|
||||
currentThread = find_thread( NULL );
|
||||
hashBucket = currentThread & 0x000000FF;
|
||||
|
||||
/*
|
||||
** Grab the proper hash table based on the passed index.
|
||||
*/
|
||||
|
||||
hashTable = bt_privateRoot.keys[index];
|
||||
|
||||
if( 0 == hashTable )
|
||||
{
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
** Search through the linked list the end is reached or an existing
|
||||
** entry is found.
|
||||
*/
|
||||
|
||||
currentEntry = hashTable->next[ hashBucket ];
|
||||
|
||||
while( currentEntry != 0 )
|
||||
{
|
||||
if( currentEntry->threadID == currentThread )
|
||||
{
|
||||
/*
|
||||
** Found a structure previously created for this thread.
|
||||
** Copy out the data, unlock, and return.
|
||||
*/
|
||||
|
||||
tempPointer = currentEntry->data;
|
||||
return( tempPointer );
|
||||
}
|
||||
|
||||
currentEntry = currentEntry->next;
|
||||
}
|
||||
|
||||
/*
|
||||
** Ooops, we ran out of entries. This thread isn't listed.
|
||||
*/
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void*)
|
||||
PR_GetThreadPrivate (PRUintn index)
|
||||
{
|
||||
void *returnValue;
|
||||
|
||||
PR_Lock( bt_privateRoot.lock );
|
||||
returnValue = _bt_getThreadPrivate( index );
|
||||
PR_Unlock( bt_privateRoot.lock );
|
||||
|
||||
return( returnValue );
|
||||
}
|
||||
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_Interrupt (PRThread* thred)
|
||||
{
|
||||
PRIntn rv;
|
||||
|
||||
PR_ASSERT(thred != NULL);
|
||||
rv = resume_thread( thred->md.tid );
|
||||
|
||||
if( rv == B_BAD_THREAD_STATE )
|
||||
{
|
||||
/*
|
||||
** We have a thread that's not suspended, but is
|
||||
** blocked. Suspend it THEN resume it. The
|
||||
** function call that's hanging will return
|
||||
** B_INTERRUPTED
|
||||
*/
|
||||
|
||||
rv = suspend_thread( thred->md.tid );
|
||||
if( rv != B_NO_ERROR )
|
||||
{
|
||||
PR_SetError( PR_UNKNOWN_ERROR, rv );
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
rv = resume_thread( thred->md.tid );
|
||||
if( rv != B_NO_ERROR )
|
||||
{
|
||||
PR_SetError( PR_UNKNOWN_ERROR, rv );
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
}
|
||||
|
||||
if( rv != B_NO_ERROR )
|
||||
{
|
||||
PR_SetError( PR_UNKNOWN_ERROR, rv );
|
||||
return( PR_FAILURE );
|
||||
}
|
||||
|
||||
return( PR_SUCCESS );
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PR_ClearInterrupt ()
|
||||
{
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_Yield ()
|
||||
{
|
||||
/* we just sleep for long enough to cause a reschedule (100
|
||||
microseconds) */
|
||||
snooze(100);
|
||||
}
|
||||
|
||||
#define BT_MILLION 1000000UL
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_Sleep (PRIntervalTime ticks)
|
||||
{
|
||||
bigtime_t tps;
|
||||
status_t status;
|
||||
|
||||
if (!_pr_initialized) _PR_ImplicitInitialization();
|
||||
|
||||
tps = PR_IntervalToMicroseconds( ticks );
|
||||
|
||||
status = snooze(tps);
|
||||
if (status == B_NO_ERROR) return PR_SUCCESS;
|
||||
|
||||
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, status);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
PR_Cleanup ()
|
||||
{
|
||||
PRThread *me = PR_CurrentThread();
|
||||
|
||||
PR_ASSERT(me->state & BT_THREAD_PRIMORD);
|
||||
if ((me->state & BT_THREAD_PRIMORD) == 0) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_Lock( bt_book.ml );
|
||||
|
||||
while( bt_book.threadCount > 0 )
|
||||
{
|
||||
PR_Unlock( bt_book.ml );
|
||||
PR_WaitCondVar(bt_book.cv, PR_INTERVAL_NO_TIMEOUT);
|
||||
PR_Lock( bt_book.ml );
|
||||
}
|
||||
|
||||
PR_Unlock( bt_book.ml );
|
||||
|
||||
#if 0
|
||||
/* I am not sure if it's safe to delete the cv and lock here, since
|
||||
* there may still be "system" threads around. If this call isn't
|
||||
* immediately prior to exiting, then there's a problem. */
|
||||
if (0 == bt_book.system) {
|
||||
PR_DestroyCondVar(bt_book.cv); bt_book.cv = NULL;
|
||||
PR_DestroyLock(bt_book.ml); bt_book.ml = NULL;
|
||||
}
|
||||
PR_DELETE(me);
|
||||
#endif
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PR_ProcessExit (PRIntn status)
|
||||
{
|
||||
exit(status);
|
||||
}
|
||||
18
mozilla/nsprpub/pr/src/bthreads/objs.mk
Normal file
18
mozilla/nsprpub/pr/src/bthreads/objs.mk
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (the "MPL"); you may not use this file except in
|
||||
# compliance with the MPL. You may obtain a copy of the MPL at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# MPL.
|
||||
#
|
||||
|
||||
# This makefile appends to the variable OBJS the bthread object modules
|
||||
# that will be part of the nspr20 library.
|
||||
|
||||
include bthreads/bsrcs.mk
|
||||
|
||||
OBJS += $(BTCSRCS:%.c=bthreads/$(OBJDIR)/%.$(OBJ_SUFFIX))
|
||||
28
mozilla/nsprpub/pr/src/md/beos/Makefile
Normal file
28
mozilla/nsprpub/pr/src/md/beos/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (the "MPL"); you may not use this file except in
|
||||
# compliance with the MPL. You may obtain a copy of the MPL at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# MPL.
|
||||
#
|
||||
|
||||
MOD_DEPTH = ../../../..
|
||||
|
||||
include $(MOD_DEPTH)/config/config.mk
|
||||
|
||||
include bsrcs.mk
|
||||
CSRCS += $(MDCSRCS)
|
||||
|
||||
TARGETS = $(OBJS)
|
||||
|
||||
INCLUDES = -I$(DIST)/include/private -I$(DIST)/include
|
||||
|
||||
include $(MOD_DEPTH)/config/rules.mk
|
||||
|
||||
export:: $(TARGETS)
|
||||
|
||||
install:: export
|
||||
31
mozilla/nsprpub/pr/src/md/beos/bcpu.c
Normal file
31
mozilla/nsprpub/pr/src/md/beos/bcpu.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
PR_EXTERN(void) _PR_MD_INIT_CPUS();
|
||||
PR_EXTERN(void) _PR_MD_WAKEUP_CPUS();
|
||||
PR_EXTERN(void) _PR_MD_START_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_STOP_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void);
|
||||
PR_EXTERN(void) _PR_MD_CLOCK_INTERRUPT(void);
|
||||
PR_EXTERN(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone);
|
||||
PR_EXTERN(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts);
|
||||
PR_EXTERN(PRInt32) _PR_MD_GET_INTSOFF(void);
|
||||
PR_EXTERN(void) _PR_MD_SET_INTSOFF(PRInt32 _val);
|
||||
PR_EXTERN(_PRCPU*) _PR_MD_CURRENT_CPU(void);
|
||||
PR_EXTERN(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu);
|
||||
PR_EXTERN(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu);
|
||||
PR_EXTERN(PRInt32) _PR_MD_PAUSE_CPU(PRIntervalTime timeout);
|
||||
240
mozilla/nsprpub/pr/src/md/beos/beos.c
Normal file
240
mozilla/nsprpub/pr/src/md/beos/beos.c
Normal file
@ -0,0 +1,240 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
|
||||
* PRInt32* pointer to a _PRSockLen_t* pointer.
|
||||
*/
|
||||
#define _PRSockLen_t int
|
||||
|
||||
/*
|
||||
** Global lock variable used to bracket calls into rusty libraries that
|
||||
** aren't thread safe (like libc, libX, etc).
|
||||
*/
|
||||
static PRLock *_pr_rename_lock = NULL;
|
||||
static PRMonitor *_pr_Xfe_mon = NULL;
|
||||
|
||||
/*
|
||||
* Variables used by the GC code, initialized in _MD_InitSegs().
|
||||
* _pr_zero_fd should be a static variable. Unfortunately, there is
|
||||
* still some Unix-specific code left in function PR_GrowSegment()
|
||||
* in file memory/prseg.c that references it, so it needs
|
||||
* to be a global variable for now.
|
||||
*/
|
||||
PRInt32 _pr_zero_fd = -1;
|
||||
static PRLock *_pr_md_lock = NULL;
|
||||
|
||||
sigset_t timer_set;
|
||||
|
||||
void _PR_UnixInit()
|
||||
{
|
||||
struct sigaction sigact;
|
||||
int rv;
|
||||
|
||||
sigemptyset(&timer_set);
|
||||
|
||||
sigact.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = 0;
|
||||
rv = sigaction(SIGPIPE, &sigact, 0);
|
||||
PR_ASSERT(0 == rv);
|
||||
|
||||
_pr_rename_lock = PR_NewLock();
|
||||
PR_ASSERT(NULL != _pr_rename_lock);
|
||||
_pr_Xfe_mon = PR_NewMonitor();
|
||||
PR_ASSERT(NULL != _pr_Xfe_mon);
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------
|
||||
*
|
||||
* PR_Now --
|
||||
*
|
||||
* Returns the current time in microseconds since the epoch.
|
||||
* The epoch is midnight January 1, 1970 GMT.
|
||||
* The implementation is machine dependent. This is the Unix
|
||||
* implementation.
|
||||
* Cf. time_t time(time_t *tp)
|
||||
*
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
PR_IMPLEMENT(PRTime)
|
||||
PR_Now(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
PRInt64 s, us, s2us;
|
||||
|
||||
GETTIMEOFDAY(&tv);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_I2L(s, tv.tv_sec);
|
||||
LL_I2L(us, tv.tv_usec);
|
||||
LL_MUL(s, s, s2us);
|
||||
LL_ADD(s, s, us);
|
||||
return s;
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
_PR_UNIX_GetInterval()
|
||||
{
|
||||
struct timeval time;
|
||||
PRIntervalTime ticks;
|
||||
|
||||
(void)GETTIMEOFDAY(&time); /* fallicy of course */
|
||||
ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */
|
||||
ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */
|
||||
return ticks;
|
||||
} /* _PR_SUNOS_GetInterval */
|
||||
|
||||
PRIntervalTime _PR_UNIX_TicksPerSecond()
|
||||
{
|
||||
return 1000; /* this needs some work :) */
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread
|
||||
** safe. Unfortunately, neither is mozilla. To make these programs work
|
||||
** in a pre-emptive threaded environment, we need to use a lock.
|
||||
*/
|
||||
|
||||
void PR_XLock()
|
||||
{
|
||||
PR_EnterMonitor(_pr_Xfe_mon);
|
||||
}
|
||||
|
||||
void PR_XUnlock()
|
||||
{
|
||||
PR_ExitMonitor(_pr_Xfe_mon);
|
||||
}
|
||||
|
||||
PRBool PR_XIsLocked()
|
||||
{
|
||||
return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
void PR_XWait(int ms)
|
||||
{
|
||||
PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms));
|
||||
}
|
||||
|
||||
void PR_XNotify(void)
|
||||
{
|
||||
PR_Notify(_pr_Xfe_mon);
|
||||
}
|
||||
|
||||
void PR_XNotifyAll(void)
|
||||
{
|
||||
PR_NotifyAll(_pr_Xfe_mon);
|
||||
}
|
||||
|
||||
#if !defined(BEOS)
|
||||
#ifdef HAVE_BSD_FLOCK
|
||||
|
||||
#include <sys/file.h>
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_LOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = flock(f, LOCK_EX);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_TLOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = flock(f, LOCK_EX|LOCK_NB);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_UNLOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = flock(f, LOCK_UN);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#else
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_LOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = lockf(f, F_LOCK, 0);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_TLOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = lockf(f, F_TLOCK, 0);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_UNLOCKFILE (PRInt32 f)
|
||||
{
|
||||
PRInt32 rv;
|
||||
rv = lockf(f, F_ULOCK, 0);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
_PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_GETHOSTNAME (char *name, PRUint32 namelen)
|
||||
{
|
||||
PRIntn rv;
|
||||
|
||||
rv = gethostname(name, namelen);
|
||||
if (0 == rv) {
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
_PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
1535
mozilla/nsprpub/pr/src/md/beos/beos_errors.c
Normal file
1535
mozilla/nsprpub/pr/src/md/beos/beos_errors.c
Normal file
File diff suppressed because it is too large
Load Diff
783
mozilla/nsprpub/pr/src/md/beos/bfile.c
Normal file
783
mozilla/nsprpub/pr/src/md/beos/bfile.c
Normal file
@ -0,0 +1,783 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
/*
|
||||
** Global lock variable used to bracket calls into rusty libraries that
|
||||
** aren't thread safe (like libc, libX, etc).
|
||||
*/
|
||||
static PRLock *_pr_rename_lock = NULL;
|
||||
|
||||
void
|
||||
_MD_InitIO (void)
|
||||
{
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_open_dir (_MDDir *md,const char *name)
|
||||
{
|
||||
int err;
|
||||
|
||||
md->d = opendir(name);
|
||||
if (!md->d) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_OPENDIR_ERROR(err);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
char*
|
||||
_MD_read_dir (_MDDir *md, PRIntn flags)
|
||||
{
|
||||
struct dirent *de;
|
||||
int err;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* XXX: readdir() is not MT-safe
|
||||
*/
|
||||
de = readdir(md->d);
|
||||
|
||||
if (!de) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_READDIR_ERROR(err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((flags & PR_SKIP_DOT) &&
|
||||
(de->d_name[0] == '.') && (de->d_name[1] == 0))
|
||||
continue;
|
||||
|
||||
if ((flags & PR_SKIP_DOT_DOT) &&
|
||||
(de->d_name[0] == '.') && (de->d_name[1] == '.') &&
|
||||
(de->d_name[2] == 0))
|
||||
continue;
|
||||
|
||||
if ((flags & PR_SKIP_HIDDEN) && (de->d_name[1] == '.'))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
return de->d_name;
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
_MD_close_dir (_MDDir *md)
|
||||
{
|
||||
int rv = 0, err;
|
||||
|
||||
if (md->d) {
|
||||
rv = closedir(md->d);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_CLOSEDIR_ERROR(err);
|
||||
}
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
void
|
||||
_MD_make_nonblock (PRFileDesc *fd)
|
||||
{
|
||||
int blocking = 1;
|
||||
setsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_NONBLOCK, &blocking, sizeof(blocking));
|
||||
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_open (const char *name, PRIntn flags, PRIntn mode)
|
||||
{
|
||||
PRInt32 osflags;
|
||||
PRInt32 rv, err;
|
||||
|
||||
if (flags & PR_RDWR) {
|
||||
osflags = O_RDWR;
|
||||
} else if (flags & PR_WRONLY) {
|
||||
osflags = O_WRONLY;
|
||||
} else {
|
||||
osflags = O_RDONLY;
|
||||
}
|
||||
|
||||
if (flags & PR_APPEND)
|
||||
osflags |= O_APPEND;
|
||||
if (flags & PR_TRUNCATE)
|
||||
osflags |= O_TRUNC;
|
||||
if (flags & PR_SYNC) {
|
||||
/* Ummmm. BeOS doesn't appear to
|
||||
support sync in any way shape or
|
||||
form. */
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** On creations we hold the 'create' lock in order to enforce
|
||||
** the semantics of PR_Rename. (see the latter for more details)
|
||||
*/
|
||||
if (flags & PR_CREATE_FILE)
|
||||
{
|
||||
osflags |= O_CREAT ;
|
||||
if (NULL !=_pr_rename_lock)
|
||||
PR_Lock(_pr_rename_lock);
|
||||
}
|
||||
|
||||
rv = open(name, osflags, mode);
|
||||
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_OPEN_ERROR(err);
|
||||
}
|
||||
|
||||
if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
|
||||
PR_Unlock(_pr_rename_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_close_file (PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = close(osfd);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_CLOSE_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_read (PRFileDesc *fd, void *buf, PRInt32 amount)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
|
||||
rv = read( osfd, buf, amount );
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_READ_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
|
||||
rv = write( osfd, buf, amount );
|
||||
|
||||
if( rv < 0 ) {
|
||||
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_WRITE_ERROR(err);
|
||||
}
|
||||
return( rv );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_writev (PRFileDesc *fd, struct PRIOVec *iov, PRInt32 iov_size,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = lseek (fd->secret->md.osfd, offset, whence);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_LSEEK_ERROR(err);
|
||||
}
|
||||
return( rv );
|
||||
}
|
||||
|
||||
PRInt64
|
||||
_MD_lseek64 (PRFileDesc *fd, PRInt64 offset, int whence)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
/* According to the BeOS headers, lseek accepts a
|
||||
* variable of type off_t for the offset, and off_t
|
||||
* is defined to be a 64-bit value. So no special
|
||||
* cracking needs to be done on "offset".
|
||||
*/
|
||||
|
||||
rv = lseek (fd->secret->md.osfd, offset, whence);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_LSEEK_ERROR(err);
|
||||
}
|
||||
return( rv );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_fsync (PRFileDesc *fd)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = fsync(fd->secret->md.osfd);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_FSYNC_ERROR(err);
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_delete (const char *name)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = unlink(name);
|
||||
if (rv == -1)
|
||||
{
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_UNLINK_ERROR(err);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_getfileinfo (const char *fn, PRFileInfo *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt32 rv, err;
|
||||
PRInt64 s, s2us;
|
||||
|
||||
rv = stat(fn, &sb);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_STAT_ERROR(err);
|
||||
} else if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
|
||||
/* Must truncate file size for the 32 bit
|
||||
version */
|
||||
info->size = (sb.st_size & 0xffffffff);
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_getfileinfo64 (const char *fn, PRFileInfo64 *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt32 rv, err;
|
||||
PRInt64 s, s2us;
|
||||
|
||||
rv = stat(fn, &sb);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_STAT_ERROR(err);
|
||||
} else if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
|
||||
/* For the 64 bit version we can use
|
||||
* the native st_size without modification
|
||||
*/
|
||||
info->size = sb.st_size;
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_getopenfileinfo (const PRFileDesc *fd, PRFileInfo *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt64 s, s2us;
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = fstat(fd->secret->md.osfd, &sb);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_FSTAT_ERROR(err);
|
||||
} else if (info) {
|
||||
if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE ;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
/* Use lower 32 bits of file size */
|
||||
info->size = ( sb.st_size & 0xffffffff);
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_getopenfileinfo64 (const PRFileDesc *fd, PRFileInfo64 *info)
|
||||
{
|
||||
struct stat sb;
|
||||
PRInt64 s, s2us;
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = fstat(fd->secret->md.osfd, &sb);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_FSTAT_ERROR(err);
|
||||
} else if (info) {
|
||||
if (info) {
|
||||
if (S_IFREG & sb.st_mode)
|
||||
info->type = PR_FILE_FILE ;
|
||||
else if (S_IFDIR & sb.st_mode)
|
||||
info->type = PR_FILE_DIRECTORY;
|
||||
else
|
||||
info->type = PR_FILE_OTHER;
|
||||
info->size = sb.st_size;
|
||||
LL_I2L(s, sb.st_mtime);
|
||||
LL_I2L(s2us, PR_USEC_PER_SEC);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->modifyTime = s;
|
||||
LL_I2L(s, sb.st_ctime);
|
||||
LL_MUL(s, s, s2us);
|
||||
info->creationTime = s;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_rename (const char *from, const char *to)
|
||||
{
|
||||
PRInt32 rv = -1, err;
|
||||
|
||||
/*
|
||||
** This is trying to enforce the semantics of WINDOZE' rename
|
||||
** operation. That means one is not allowed to rename over top
|
||||
** of an existing file. Holding a lock across these two function
|
||||
** and the open function is known to be a bad idea, but ....
|
||||
*/
|
||||
if (NULL != _pr_rename_lock)
|
||||
PR_Lock(_pr_rename_lock);
|
||||
if (0 == access(to, F_OK))
|
||||
PR_SetError(PR_FILE_EXISTS_ERROR, 0);
|
||||
else
|
||||
{
|
||||
rv = rename(from, to);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_RENAME_ERROR(err);
|
||||
}
|
||||
}
|
||||
if (NULL != _pr_rename_lock)
|
||||
PR_Unlock(_pr_rename_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_access (const char *name, PRIntn how)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
int amode;
|
||||
|
||||
switch (how) {
|
||||
case PR_ACCESS_WRITE_OK:
|
||||
amode = W_OK;
|
||||
break;
|
||||
case PR_ACCESS_READ_OK:
|
||||
amode = R_OK;
|
||||
break;
|
||||
case PR_ACCESS_EXISTS:
|
||||
amode = F_OK;
|
||||
break;
|
||||
default:
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
rv = -1;
|
||||
goto done;
|
||||
}
|
||||
rv = access(name, amode);
|
||||
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_ACCESS_ERROR(err);
|
||||
}
|
||||
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_stat (const char *name, struct stat *buf)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_mkdir (const char *name, PRIntn mode)
|
||||
{
|
||||
status_t rv;
|
||||
int err;
|
||||
|
||||
/*
|
||||
** This lock is used to enforce rename semantics as described
|
||||
** in PR_Rename. Look there for more fun details.
|
||||
*/
|
||||
if (NULL !=_pr_rename_lock)
|
||||
PR_Lock(_pr_rename_lock);
|
||||
|
||||
rv = mkdir(name, mode);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_MKDIR_ERROR(err);
|
||||
}
|
||||
if (NULL !=_pr_rename_lock)
|
||||
PR_Unlock(_pr_rename_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_rmdir (const char *name)
|
||||
{
|
||||
int rv, err;
|
||||
|
||||
rv = rmdir(name);
|
||||
if (rv == -1) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_RMDIR_ERROR(err);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_pr_poll (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
|
||||
{
|
||||
PRPollDesc *pd, *epd;
|
||||
PRInt32 n, err, pdcnt;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
fd_set rd, wt, ex;
|
||||
struct timeval tv, *tvp = NULL;
|
||||
int maxfd = -1;
|
||||
int rv;
|
||||
|
||||
ConnectListNode currentConnectList[64];
|
||||
int currentConnectListCount = 0;
|
||||
int i,j;
|
||||
int connectResult = 0;
|
||||
int connectError = 0;
|
||||
|
||||
/*
|
||||
* For restarting _MD_SELECT() if it is interrupted by a signal.
|
||||
* We use these variables to figure out how much time has elapsed
|
||||
* and how much of the timeout still remains.
|
||||
*/
|
||||
PRIntervalTime start, elapsed, remaining;
|
||||
|
||||
FD_ZERO(&rd);
|
||||
FD_ZERO(&wt);
|
||||
FD_ZERO(&ex);
|
||||
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++) {
|
||||
PRInt32 osfd;
|
||||
PRInt16 in_flags = pd->in_flags;
|
||||
PRFileDesc *bottom = pd->fd;
|
||||
|
||||
if ((NULL == bottom) || (in_flags == 0)) {
|
||||
continue;
|
||||
}
|
||||
while (bottom->lower != NULL) {
|
||||
bottom = bottom->lower;
|
||||
}
|
||||
osfd = bottom->secret->md.osfd;
|
||||
|
||||
if( (in_flags & PR_POLL_WRITE) || (in_flags & PR_POLL_EXCEPT) ) {
|
||||
|
||||
PR_Lock( _connectLock );
|
||||
|
||||
for( i = 0; i < connectCount; i++ ) {
|
||||
|
||||
if( connectList[i].osfd == osfd ) {
|
||||
|
||||
memcpy( ¤tConnectList[currentConnectListCount], &connectList[i], sizeof( connectList[i] ) );
|
||||
currentConnectListCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock( _connectLock );
|
||||
}
|
||||
|
||||
if (in_flags & PR_POLL_READ) {
|
||||
FD_SET(osfd, &rd);
|
||||
if( osfd > maxfd ) maxfd = osfd;
|
||||
}
|
||||
}
|
||||
if (timeout != PR_INTERVAL_NO_TIMEOUT) {
|
||||
tv.tv_sec = PR_IntervalToSeconds(timeout);
|
||||
tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
|
||||
tvp = &tv;
|
||||
start = PR_IntervalNow();
|
||||
}
|
||||
|
||||
if( currentConnectListCount > 0 ) {
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100000L;
|
||||
tvp = &tv;
|
||||
start = PR_IntervalNow();
|
||||
}
|
||||
|
||||
retry:
|
||||
if( currentConnectListCount > 0 ) {
|
||||
|
||||
for( i = 0; i < currentConnectListCount; i++ ) {
|
||||
|
||||
connectResult = connect( currentConnectList[i].osfd,
|
||||
¤tConnectList[i].addr,
|
||||
¤tConnectList[i].addrlen );
|
||||
connectError = _MD_ERRNO();
|
||||
|
||||
if( ( connectResult < 0 ) &&
|
||||
( connectError == EINTR ||
|
||||
connectError == EWOULDBLOCK ||
|
||||
connectError == EINPROGRESS ||
|
||||
connectError == EALREADY ) ) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
PR_Lock( _connectLock );
|
||||
|
||||
for( j = 0; j < connectCount; j++ ) {
|
||||
|
||||
if( connectList[j].osfd == currentConnectList[i].osfd ) {
|
||||
|
||||
if( j == ( connectCount - 1 ) ) {
|
||||
|
||||
connectList[j].osfd = -1;
|
||||
|
||||
} else {
|
||||
|
||||
for( ; j < connectCount; j++ )
|
||||
memcpy( &connectList[j], &connectList[j+1], sizeof( connectList[j] ) );
|
||||
}
|
||||
connectCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PR_Unlock( _connectLock );
|
||||
|
||||
FD_ZERO( &rd );
|
||||
FD_SET( currentConnectList[i].osfd, &wt );
|
||||
FD_SET( currentConnectList[i].osfd, &ex );
|
||||
n = 1;
|
||||
goto afterselect;
|
||||
}
|
||||
}
|
||||
|
||||
if( maxfd == -1 ) {
|
||||
snooze( 100000L );
|
||||
goto retry;
|
||||
}
|
||||
n = select(maxfd + 1, &rd, NULL, NULL, tvp);
|
||||
afterselect:
|
||||
if ( (n == -1 && errno == EINTR) || (n == 0 && currentConnectListCount > 0 ) ) {
|
||||
if (timeout == PR_INTERVAL_NO_TIMEOUT) {
|
||||
goto retry;
|
||||
} else {
|
||||
elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
|
||||
if (elapsed > timeout) {
|
||||
n = 0; /* timed out */
|
||||
} else {
|
||||
remaining = timeout - elapsed;
|
||||
tv.tv_sec = PR_IntervalToSeconds(remaining);
|
||||
tv.tv_usec = PR_IntervalToMicroseconds(
|
||||
remaining - PR_SecondsToInterval(tv.tv_sec));
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
n = 0;
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++) {
|
||||
PRInt32 osfd;
|
||||
PRInt16 in_flags = pd->in_flags;
|
||||
PRInt16 out_flags = 0;
|
||||
PRFileDesc *bottom = pd->fd;
|
||||
|
||||
if ((NULL == bottom) || (in_flags == 0)) {
|
||||
pd->out_flags = 0;
|
||||
continue;
|
||||
}
|
||||
while (bottom->lower != NULL) {
|
||||
bottom = bottom->lower;
|
||||
}
|
||||
osfd = bottom->secret->md.osfd;
|
||||
|
||||
if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, &rd)) {
|
||||
out_flags |= PR_POLL_READ;
|
||||
}
|
||||
if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, &wt)) {
|
||||
out_flags |= PR_POLL_WRITE;
|
||||
}
|
||||
if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, &ex)) {
|
||||
out_flags |= PR_POLL_EXCEPT;
|
||||
}
|
||||
|
||||
if ( FD_ISSET(osfd, &wt) && FD_ISSET(osfd, &ex ) ) {
|
||||
|
||||
bottom->secret->md.connectReturnValue = connectResult;
|
||||
bottom->secret->md.connectReturnError = connectError;
|
||||
bottom->secret->md.connectValueValid = PR_TRUE;
|
||||
}
|
||||
|
||||
pd->out_flags = out_flags;
|
||||
if (out_flags) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
PR_ASSERT(n > 0);
|
||||
} else if (n < 0) {
|
||||
err = _MD_ERRNO();
|
||||
if (err == EBADF) {
|
||||
/* Find the bad fds */
|
||||
n = 0;
|
||||
for (pd = pds, epd = pd + npds; pd < epd; pd++) {
|
||||
int optval;
|
||||
int optlen = sizeof(optval);
|
||||
PRFileDesc *bottom = pd->fd;
|
||||
|
||||
pd->out_flags = 0;
|
||||
if ((NULL == bottom) || (pd->in_flags == 0)) {
|
||||
continue;
|
||||
}
|
||||
while (bottom->lower != NULL) {
|
||||
bottom = bottom->lower;
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* BeOS doesn't have this feature of getsockopt.
|
||||
*/
|
||||
if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
|
||||
SO_TYPE, (char *) &optval, &optlen) == -1) {
|
||||
PR_ASSERT(_MD_ERRNO() == ENOTSOCK);
|
||||
if (_MD_ERRNO() == ENOTSOCK) {
|
||||
pd->out_flags = PR_POLL_NVAL;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
PR_ASSERT(n > 0);
|
||||
} else {
|
||||
PR_ASSERT(err != EINTR); /* should have been handled above */
|
||||
_PR_MD_MAP_SELECT_ERROR(err);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* File locking.
|
||||
*/
|
||||
|
||||
PRStatus
|
||||
_MD_lockfile (PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv;
|
||||
struct flock linfo;
|
||||
|
||||
linfo.l_type =
|
||||
linfo.l_whence = SEEK_SET;
|
||||
linfo.l_start = 0;
|
||||
linfo.l_len = 0;
|
||||
|
||||
rv = fcntl(osfd, F_SETLKW, &linfo);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_tlockfile (PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv;
|
||||
struct flock linfo;
|
||||
|
||||
linfo.l_type =
|
||||
linfo.l_whence = SEEK_SET;
|
||||
linfo.l_start = 0;
|
||||
linfo.l_len = 0;
|
||||
|
||||
rv = fcntl(osfd, F_SETLK, &linfo);
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_unlockfile (PRInt32 osfd)
|
||||
{
|
||||
PRInt32 rv;
|
||||
struct flock linfo;
|
||||
|
||||
linfo.l_type =
|
||||
linfo.l_whence = SEEK_SET;
|
||||
linfo.l_start = 0;
|
||||
linfo.l_len = 0;
|
||||
|
||||
rv = fcntl(osfd, F_UNLCK, &linfo);
|
||||
|
||||
if (rv == 0)
|
||||
return PR_SUCCESS;
|
||||
|
||||
_PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
18
mozilla/nsprpub/pr/src/md/beos/bmemory.c
Normal file
18
mozilla/nsprpub/pr/src/md/beos/bmemory.c
Normal file
@ -0,0 +1,18 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
PR_EXTERN(void) _PR_MD_INIT_SEGS(void);
|
||||
PR_EXTERN(PRStatus) _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr);
|
||||
PR_EXTERN(void) _PR_MD_FREE_SEGMENT(PRSegment *seg);
|
||||
92
mozilla/nsprpub/pr/src/md/beos/bmisc.c
Normal file
92
mozilla/nsprpub/pr/src/md/beos/bmisc.c
Normal file
@ -0,0 +1,92 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
PRLock *_connectLock = NULL;
|
||||
PRUint32 connectCount = 0;
|
||||
ConnectListNode connectList[64];
|
||||
|
||||
void
|
||||
_MD_cleanup_before_exit (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_MD_exit (PRIntn status)
|
||||
{
|
||||
exit(status);
|
||||
}
|
||||
|
||||
void
|
||||
_MD_early_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
static PRLock *monitor = NULL;
|
||||
|
||||
void
|
||||
_MD_final_init (void)
|
||||
{
|
||||
_connectLock = PR_NewLock();
|
||||
PR_ASSERT(NULL != _connectLock);
|
||||
connectCount = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_MD_AtomicInit (void)
|
||||
{
|
||||
if (monitor == NULL) {
|
||||
monitor = PR_NewLock();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This is exceedingly messy. atomic_add returns the last value, NSPR expects the new value.
|
||||
** We just add or subtract 1 from the result. The actual memory update is atomic.
|
||||
*/
|
||||
|
||||
PRInt32
|
||||
_MD_AtomicAdd( PRInt32 *ptr, PRInt32 val )
|
||||
{
|
||||
return( ( atomic_add( (long *)ptr, val ) ) + val );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_AtomicIncrement( PRInt32 *val )
|
||||
{
|
||||
return( ( atomic_add( (long *)val, 1 ) ) + 1 );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_AtomicDecrement( PRInt32 *val )
|
||||
{
|
||||
return( ( atomic_add( (long *)val, -1 ) ) - 1 );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_AtomicSet( PRInt32 *val, PRInt32 newval )
|
||||
{
|
||||
PRInt32 rv;
|
||||
|
||||
if (!_pr_initialized) {
|
||||
_PR_ImplicitInitialization();
|
||||
}
|
||||
PR_Lock(monitor);
|
||||
rv = *val;
|
||||
*val = newval;
|
||||
PR_Unlock(monitor);
|
||||
return rv;
|
||||
}
|
||||
39
mozilla/nsprpub/pr/src/md/beos/bmmap.c
Normal file
39
mozilla/nsprpub/pr/src/md/beos/bmmap.c
Normal file
@ -0,0 +1,39 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
PR_EXTERN(PRStatus)
|
||||
_PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size)
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_EXTERN(void *)
|
||||
_PR_MD_MEM_MAP(PRFileMap *fmap, PRInt64 offset, PRUint32 len)
|
||||
{
|
||||
PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
PR_EXTERN(PRStatus)
|
||||
_PR_MD_MEM_UNMAP(void *addr, PRUint32 size)
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PR_EXTERN(PRStatus)
|
||||
_PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap)
|
||||
{
|
||||
return PR_FAILURE;
|
||||
}
|
||||
648
mozilla/nsprpub/pr/src/md/beos/bnet.c
Normal file
648
mozilla/nsprpub/pr/src/md/beos/bnet.c
Normal file
@ -0,0 +1,648 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
/*
|
||||
* Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
|
||||
* PRInt32* pointer to a _PRSockLen_t* pointer.
|
||||
*/
|
||||
#define _PRSockLen_t int
|
||||
|
||||
/*
|
||||
** Global lock variable used to bracket calls into rusty libraries that
|
||||
** aren't thread safe (like libc, libX, etc).
|
||||
*/
|
||||
static PRLock *_pr_rename_lock = NULL;
|
||||
static PRMonitor *_pr_Xfe_mon = NULL;
|
||||
|
||||
/*
|
||||
** This is a support routine to handle "deferred" i/o on sockets.
|
||||
** It uses "select", so it is subject to all of the BeOS limitations
|
||||
** (only READ notification, only sockets)
|
||||
*/
|
||||
#define READ_FD 1
|
||||
#define WRITE_FD 2
|
||||
|
||||
static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 rv = -1;
|
||||
struct timeval tv, *tvp;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
PRIntervalTime epoch, now, elapsed, remaining;
|
||||
PRInt32 syserror;
|
||||
fd_set rd_wr;
|
||||
|
||||
switch (timeout) {
|
||||
case PR_INTERVAL_NO_WAIT:
|
||||
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
|
||||
break;
|
||||
case PR_INTERVAL_NO_TIMEOUT:
|
||||
/*
|
||||
* This is a special case of the 'default' case below.
|
||||
* Please see the comments there.
|
||||
*/
|
||||
tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
|
||||
tv.tv_usec = 0;
|
||||
tvp = &tv;
|
||||
FD_ZERO(&rd_wr);
|
||||
do {
|
||||
FD_SET(osfd, &rd_wr);
|
||||
if (fd_type == READ_FD)
|
||||
rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
|
||||
else
|
||||
rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
|
||||
if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
|
||||
if (syserror == EBADF) {
|
||||
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
|
||||
} else {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, syserror);
|
||||
}
|
||||
if( _PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (rv == 0 || (rv == -1 && syserror == EINTR));
|
||||
break;
|
||||
default:
|
||||
now = epoch = PR_IntervalNow();
|
||||
remaining = timeout;
|
||||
tvp = &tv;
|
||||
FD_ZERO(&rd_wr);
|
||||
do {
|
||||
/*
|
||||
* We block in _MD_SELECT for at most
|
||||
* _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
|
||||
* so that there is an upper limit on the delay
|
||||
* before the interrupt bit is checked.
|
||||
*/
|
||||
tv.tv_sec = PR_IntervalToSeconds(remaining);
|
||||
if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
|
||||
tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
|
||||
tv.tv_usec = 0;
|
||||
} else {
|
||||
tv.tv_usec = PR_IntervalToMicroseconds(
|
||||
remaining -
|
||||
PR_SecondsToInterval(tv.tv_sec));
|
||||
}
|
||||
FD_SET(osfd, &rd_wr);
|
||||
if (fd_type == READ_FD)
|
||||
rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
|
||||
else
|
||||
rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
|
||||
/*
|
||||
* we don't consider EINTR a real error
|
||||
*/
|
||||
if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
|
||||
if (syserror == EBADF) {
|
||||
PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
|
||||
} else {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, syserror);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (_PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We loop again if _MD_SELECT timed out or got interrupted
|
||||
* by a signal, and the timeout deadline has not passed yet.
|
||||
*/
|
||||
if (rv == 0 || (rv == -1 && syserror == EINTR)) {
|
||||
/*
|
||||
* If _MD_SELECT timed out, we know how much time
|
||||
* we spent in blocking, so we can avoid a
|
||||
* PR_IntervalNow() call.
|
||||
*/
|
||||
if (rv == 0) {
|
||||
now += PR_SecondsToInterval(tv.tv_sec)
|
||||
+ PR_MicrosecondsToInterval(tv.tv_usec);
|
||||
} else {
|
||||
now = PR_IntervalNow();
|
||||
}
|
||||
elapsed = (PRIntervalTime) (now - epoch);
|
||||
if (elapsed >= timeout) {
|
||||
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
|
||||
rv = -1;
|
||||
break;
|
||||
} else {
|
||||
remaining = timeout - elapsed;
|
||||
}
|
||||
}
|
||||
} while (rv == 0 || (rv == -1 && syserror == EINTR));
|
||||
break;
|
||||
}
|
||||
return(rv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRInt32
|
||||
_MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) {
|
||||
_PR_MD_MAP_RECV_ERROR(EPIPE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((rv = recv(osfd, buf, amount, flags)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
/* If socket was supposed to be blocking,
|
||||
wait a while for the condition to be
|
||||
satisfied. */
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
|
||||
continue;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_RECV_ERROR(err);
|
||||
}
|
||||
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
|
||||
PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while ((*addrlen = PR_NETADDR_SIZE(addr)),
|
||||
((rv = recvfrom(osfd, buf, amount, flags,
|
||||
(struct sockaddr *) addr,
|
||||
(_PRSockLen_t *)addrlen)) == -1)) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
|
||||
continue;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_RECVFROM_ERROR(err);
|
||||
}
|
||||
|
||||
done:
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE)
|
||||
{
|
||||
_PR_MD_MAP_SEND_ERROR(EPIPE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((rv = send(osfd, buf, amount, flags)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
|
||||
if( _PR_PENDING_INTERRUPT(me)) {
|
||||
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* in UNIX implementations, you could do a socket_io_wait here.
|
||||
* but since BeOS doesn't yet support WRITE notification in select,
|
||||
* you're spanked.
|
||||
*/
|
||||
snooze( 10000L );
|
||||
continue;
|
||||
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
|
||||
continue;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_SEND_ERROR(err);
|
||||
}
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
|
||||
const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while ((rv = sendto(osfd, buf, amount, flags,
|
||||
(struct sockaddr *) addr, addrlen)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
|
||||
printf( "This should be a blocking sendto call!!!\n" );
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
|
||||
continue;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_SENDTO_ERROR(err);
|
||||
}
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
while ((rv = accept(osfd, (struct sockaddr *) addr,
|
||||
(_PRSockLen_t *)addrlen)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
|
||||
if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
|
||||
if (fd->secret->nonblocking) {
|
||||
break;
|
||||
}
|
||||
/* If it's SUPPOSED to be a blocking thread, wait
|
||||
* a while to see if the triggering condition gets
|
||||
* satisfied.
|
||||
*/
|
||||
/* Assume that we're always using a native thread */
|
||||
if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
|
||||
goto done;
|
||||
} else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr) addr->raw.family = AF_INET;
|
||||
|
||||
if (rv < 0) {
|
||||
_PR_MD_MAP_ACCEPT_ERROR(err);
|
||||
}
|
||||
done:
|
||||
#ifdef _PR_HAVE_SOCKADDR_LEN
|
||||
if (rv != -1) {
|
||||
/* Mask off the first byte of struct sockaddr (the length field) */
|
||||
if (addr) {
|
||||
*((unsigned char *) addr) = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
addr->raw.family = ntohs(addr->raw.family);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* _PR_HAVE_SOCKADDR_LEN */
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
PRInt32 osfd = fd->secret->md.osfd;
|
||||
PRInt32 rv, err;
|
||||
PRThread *me = _PR_MD_CURRENT_THREAD();
|
||||
|
||||
fd->secret->md.connectValueValid = PR_FALSE;
|
||||
|
||||
retry:
|
||||
if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
|
||||
err = _MD_ERRNO();
|
||||
fd->secret->md.connectReturnValue = rv;
|
||||
fd->secret->md.connectReturnError = err;
|
||||
fd->secret->md.connectValueValid = PR_TRUE;
|
||||
|
||||
if( err == EINTR ) {
|
||||
|
||||
if( _PR_PENDING_INTERRUPT(me)) {
|
||||
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
snooze( 100000L );
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) {
|
||||
|
||||
/*
|
||||
** There's no timeout on this connect, but that's not
|
||||
** a big deal, since the connect times out anyways
|
||||
** after 30 seconds. Just sleep for 1/10th of a second
|
||||
** and retry until we go through or die.
|
||||
*/
|
||||
|
||||
if( _PR_PENDING_INTERRUPT(me)) {
|
||||
me->flags &= ~_PR_INTERRUPT;
|
||||
PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
|
||||
PR_Lock(_connectLock);
|
||||
connectList[connectCount].osfd = osfd;
|
||||
memcpy(&connectList[connectCount].addr, addr, addrlen);
|
||||
connectList[connectCount].addrlen = addrlen;
|
||||
connectList[connectCount].timeout = timeout;
|
||||
connectCount++;
|
||||
PR_Unlock(_connectLock);
|
||||
_PR_MD_MAP_CONNECT_ERROR(err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
_PR_MD_MAP_CONNECT_ERROR(err);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
|
||||
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_BIND_ERROR(err);
|
||||
}
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_listen (PRFileDesc *fd, PRIntn backlog)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
/* Bug workaround! Setting listen to 0 on Be accepts no connections.
|
||||
** On most UN*Xes this sets the default.
|
||||
*/
|
||||
|
||||
if( backlog == 0 ) backlog = 5;
|
||||
|
||||
rv = listen(fd->secret->md.osfd, backlog);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_LISTEN_ERROR(err);
|
||||
}
|
||||
|
||||
return(rv);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_shutdown (PRFileDesc *fd, PRIntn how)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
if (how == PR_SHUTDOWN_SEND)
|
||||
fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
|
||||
else if (how == PR_SHUTDOWN_RCV)
|
||||
fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
|
||||
else if (how == PR_SHUTDOWN_BOTH) {
|
||||
fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_socketpair (int af, int type, int flags, PRInt32 *osfd)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_close_socket (PRInt32 osfd)
|
||||
{
|
||||
closesocket( osfd );
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getsockname(fd->secret->md.osfd,
|
||||
(struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
|
||||
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_GETSOCKNAME_ERROR(err);
|
||||
}
|
||||
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getpeername(fd->secret->md.osfd,
|
||||
(struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
|
||||
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_GETPEERNAME_ERROR(err);
|
||||
}
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_getsockopt (PRFileDesc *fd, PRInt32 level,
|
||||
PRInt32 optname, char* optval, PRInt32* optlen)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
|
||||
#if 0
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = getsockopt(fd->secret->md.osfd, level, optname,
|
||||
optval, (_PRSockLen_t *)optlen);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_GETSOCKOPT_ERROR(err);
|
||||
}
|
||||
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_setsockopt (PRFileDesc *fd, PRInt32 level,
|
||||
PRInt32 optname, const char* optval, PRInt32 optlen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
|
||||
if (rv < 0) {
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_SETSOCKOPT_ERROR(err);
|
||||
}
|
||||
return rv==0?PR_SUCCESS:PR_FAILURE;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
|
||||
void *buf, PRInt32 amount, PRIntervalTime timeout)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_transmitfile (PRFileDesc *sock, PRFileDesc *file, const void *headers, PRInt32 hlen, PRInt32 flags, PRIntervalTime timeout)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_socket (int af, int type, int flags)
|
||||
{
|
||||
PRInt32 osfd, err;
|
||||
|
||||
osfd = socket( af, type, 0 );
|
||||
|
||||
if( -1 == osfd ) {
|
||||
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_SOCKET_ERROR( err );
|
||||
}
|
||||
|
||||
return( osfd );
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_socketavailable (PRFileDesc *fd)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_get_socket_error (void)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_gethostname (char *name, PRUint32 namelen)
|
||||
{
|
||||
PRInt32 rv, err;
|
||||
|
||||
rv = gethostname(name, namelen);
|
||||
if (rv == 0)
|
||||
{
|
||||
err = _MD_ERRNO();
|
||||
_PR_MD_MAP_GETHOSTNAME_ERROR(err);
|
||||
return PR_FAILURE;
|
||||
}
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
|
||||
{
|
||||
int rv;
|
||||
int flags = 0;
|
||||
|
||||
if( fd->secret->md.connectValueValid == PR_TRUE )
|
||||
|
||||
if( fd->secret->md.connectReturnValue == -1 )
|
||||
|
||||
return fd->secret->md.connectReturnError;
|
||||
else
|
||||
return 0; /* No error */
|
||||
|
||||
rv = recv(fd->secret->md.osfd, NULL, 0, flags);
|
||||
PR_ASSERT(-1 == rv || 0 == rv);
|
||||
if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
return errno;
|
||||
}
|
||||
return 0; /* no error */
|
||||
}
|
||||
39
mozilla/nsprpub/pr/src/md/beos/bproc.c
Normal file
39
mozilla/nsprpub/pr/src/md/beos/bproc.c
Normal file
@ -0,0 +1,39 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
PRProcess*
|
||||
_MD_create_process (const char *path, char *const *argv,
|
||||
char *const *envp, const PRProcessAttr *attr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_detach_process (PRProcess *process)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_wait_process (PRProcess *process, PRInt32 *exitCode)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PRStatus
|
||||
_MD_kill_process (PRProcess *process)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
35
mozilla/nsprpub/pr/src/md/beos/bseg.c
Normal file
35
mozilla/nsprpub/pr/src/md/beos/bseg.c
Normal file
@ -0,0 +1,35 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
void
|
||||
_PR_InitSegs (void)
|
||||
{
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
_MD_init_segs (void)
|
||||
{
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(PRStatus)
|
||||
_MD_alloc_segment (PRSegment *seg, PRUint32 size, void *vaddr)
|
||||
{
|
||||
return PR_NOT_IMPLEMENTED_ERROR;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
_MD_free_segment (PRSegment *seg)
|
||||
{
|
||||
}
|
||||
27
mozilla/nsprpub/pr/src/md/beos/bsrcs.mk
Normal file
27
mozilla/nsprpub/pr/src/md/beos/bsrcs.mk
Normal file
@ -0,0 +1,27 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (the "MPL"); you may not use this file except in
|
||||
# compliance with the MPL. You may obtain a copy of the MPL at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# MPL.
|
||||
#
|
||||
|
||||
# this file lists the source files to be compiled (used in Makefile) and
|
||||
# then enumerated as object files (in objs.mk) for inclusion in the NSPR
|
||||
# shared library
|
||||
|
||||
MDCSRCS = \
|
||||
beos.c \
|
||||
beos_errors.c \
|
||||
bfile.c \
|
||||
bmisc.c \
|
||||
bnet.c \
|
||||
bproc.c \
|
||||
bseg.c \
|
||||
btime.c \
|
||||
bmmap.c \
|
||||
$(NULL)
|
||||
51
mozilla/nsprpub/pr/src/md/beos/btime.c
Normal file
51
mozilla/nsprpub/pr/src/md/beos/btime.c
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (the "MPL"); you may not use this file except in
|
||||
* compliance with the MPL. You may obtain a copy of the MPL at
|
||||
* http:// www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* MPL.
|
||||
*/
|
||||
|
||||
#include "primpl.h"
|
||||
#include <kernel/OS.h>
|
||||
|
||||
static bigtime_t start;
|
||||
|
||||
PRTime
|
||||
_MD_now (void)
|
||||
{
|
||||
return (PRTime)real_time_clock_usecs();
|
||||
}
|
||||
|
||||
void
|
||||
_MD_interval_init (void)
|
||||
{
|
||||
/* grab the base interval time */
|
||||
start = real_time_clock_usecs();
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
_MD_get_interval (void)
|
||||
{
|
||||
return( (PRIntervalTime) real_time_clock_usecs() / 10 );
|
||||
|
||||
#if 0
|
||||
/* return the number of tens of microseconds that have elapsed since
|
||||
we were initialized */
|
||||
bigtime_t now = real_time_clock_usecs();
|
||||
now -= start;
|
||||
now /= 10;
|
||||
return (PRIntervalTime)now;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
_MD_interval_per_sec (void)
|
||||
{
|
||||
return 100000L;
|
||||
}
|
||||
18
mozilla/nsprpub/pr/src/md/beos/objs.mk
Normal file
18
mozilla/nsprpub/pr/src/md/beos/objs.mk
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (the "MPL"); you may not use this file except in
|
||||
# compliance with the MPL. You may obtain a copy of the MPL at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the MPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# MPL.
|
||||
#
|
||||
|
||||
# This makefile appends to the variable OBJS the platform-dependent
|
||||
# object modules that will be part of the nspr20 library.
|
||||
|
||||
include md/beos/bsrcs.mk
|
||||
|
||||
OBJS += $(MDCSRCS:%.c=md/beos/$(OBJDIR)/%.$(OBJ_SUFFIX))
|
||||
Loading…
x
Reference in New Issue
Block a user