[svn r136] MAJOR UNSTABLE UPDATE!!!

Initial commit after moving to Tango instead of Phobos.

Lots of bugfixes...

This build is not suitable for most things.
This commit is contained in:
Tomas Lindquist Olsen
2008-01-11 17:57:40 +01:00
parent bc08c6fcb1
commit b15b3484c8
524 changed files with 270705 additions and 175 deletions
+286
View File
@@ -0,0 +1,286 @@
/**
* This module contains a collection of bit-level operations.
*
* Copyright: Public Domain
* License: Public Domain
* Authors: Sean Kelly
*/
module tango.core.BitManip;
version( DDoc )
{
/**
* Scans the bits in v starting with bit 0, looking
* for the first set bit.
* Returns:
* The bit number of the first bit set.
* The return value is undefined if v is zero.
*/
int bsf( uint v );
/**
* Scans the bits in v from the most significant bit
* to the least significant bit, looking
* for the first set bit.
* Returns:
* The bit number of the first bit set.
* The return value is undefined if v is zero.
* Example:
* ---
* import std.intrinsic;
*
* int main()
* {
* uint v;
* int x;
*
* v = 0x21;
* x = bsf(v);
* printf("bsf(x%x) = %d\n", v, x);
* x = bsr(v);
* printf("bsr(x%x) = %d\n", v, x);
* return 0;
* }
* ---
* Output:
* bsf(x21) = 0<br>
* bsr(x21) = 5
*/
int bsr( uint v );
/**
* Tests the bit.
*/
int bt( uint* p, uint bitnum );
/**
* Tests and complements the bit.
*/
int btc( uint* p, uint bitnum );
/**
* Tests and resets (sets to 0) the bit.
*/
int btr( uint* p, uint bitnum );
/**
* Tests and sets the bit.
* Params:
* p = a non-NULL pointer to an array of uints.
* index = a bit number, starting with bit 0 of p[0],
* and progressing. It addresses bits like the expression:
---
p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
---
* Returns:
* A non-zero value if the bit was set, and a zero
* if it was clear.
*
* Example:
* ---
import std.intrinsic;
int main()
{
uint array[2];
array[0] = 2;
array[1] = 0x100;
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
return 0;
}
* ---
* Output:
<pre>
btc(array, 35) = 0
array = [0]:x2, [1]:x108
btc(array, 35) = -1
array = [0]:x2, [1]:x100
bts(array, 35) = 0
array = [0]:x2, [1]:x108
btr(array, 35) = -1
array = [0]:x2, [1]:x100
bt(array, 1) = -1
array = [0]:x2, [1]:x100
</pre>
*/
int bts( uint* p, uint bitnum );
/**
* Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
* byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
* becomes byte 0.
*/
uint bswap( uint v );
/**
* Reads I/O port at port_address.
*/
ubyte inp( uint port_address );
/**
* ditto
*/
ushort inpw( uint port_address );
/**
* ditto
*/
uint inpl( uint port_address );
/**
* Writes and returns value to I/O port at port_address.
*/
ubyte outp( uint port_address, ubyte value );
/**
* ditto
*/
ushort outpw( uint port_address, ushort value );
/**
* ditto
*/
uint outpl( uint port_address, uint value );
}
else
{
public import std.intrinsic;
}
/**
* Calculates the number of set bits in a 32-bit integer.
*/
int popcnt( uint x )
{
// Avoid branches, and the potential for cache misses which
// could be incurred with a table lookup.
// We need to mask alternate bits to prevent the
// sum from overflowing.
// add neighbouring bits. Each bit is 0 or 1.
x = x - ((x>>1) & 0x5555_5555);
// now each two bits of x is a number 00,01 or 10.
// now add neighbouring pairs
x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333);
// now each nibble holds 0000-0100. Adding them won't
// overflow any more, so we don't need to mask any more
// Now add the nibbles, then the bytes, then the words
// We still need to mask to prevent double-counting.
// Note that if we used a rotate instead of a shift, we
// wouldn't need the masks, and could just divide the sum
// by 8 to account for the double-counting.
// On some CPUs, it may be faster to perform a multiply.
x += (x>>4);
x &= 0x0F0F_0F0F;
x += (x>>8);
x &= 0x00FF_00FF;
x += (x>>16);
x &= 0xFFFF;
return x;
}
debug( UnitTest )
{
unittest
{
assert( popcnt( 0 ) == 0 );
assert( popcnt( 7 ) == 3 );
assert( popcnt( 0xAA )== 4 );
assert( popcnt( 0x8421_1248 ) == 8 );
assert( popcnt( 0xFFFF_FFFF ) == 32 );
assert( popcnt( 0xCCCC_CCCC ) == 16 );
assert( popcnt( 0x7777_7777 ) == 24 );
}
}
/**
* Reverses the order of bits in a 32-bit integer.
*/
uint bitswap( uint x )
{
version( D_InlineAsm_X86 )
{
asm
{
// Author: Tiago Gasiba.
mov EDX, EAX;
shr EAX, 1;
and EDX, 0x5555_5555;
and EAX, 0x5555_5555;
shl EDX, 1;
or EAX, EDX;
mov EDX, EAX;
shr EAX, 2;
and EDX, 0x3333_3333;
and EAX, 0x3333_3333;
shl EDX, 2;
or EAX, EDX;
mov EDX, EAX;
shr EAX, 4;
and EDX, 0x0f0f_0f0f;
and EAX, 0x0f0f_0f0f;
shl EDX, 4;
or EAX, EDX;
bswap EAX;
}
}
else
{
// swap odd and even bits
x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1);
// swap consecutive pairs
x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2);
// swap nibbles
x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4);
// swap bytes
x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8);
// swap 2-byte long pairs
x = ( x >> 16 ) | ( x << 16);
return x;
}
}
debug( UnitTest )
{
unittest
{
assert( bitswap( 0x8000_0100 ) == 0x0080_0001 );
}
}
+622
View File
@@ -0,0 +1,622 @@
/**
* The exception module defines all system-level exceptions and provides a
* mechanism to alter system-level error handling.
*
* Copyright: Copyright (C) 2005-2006 Sean Kelly, Kris Bell. All rights reserved.
* License: BSD style: $(LICENSE)
* Authors: Sean Kelly, Kris Bell
*/
module tango.core.Exception;
private
{
alias void function( char[] file, size_t line, char[] msg = null ) assertHandlerType;
alias TracedExceptionInfo function( void* ptr = null ) traceHandlerType;
assertHandlerType assertHandler = null;
traceHandlerType traceHandler = null;
}
interface TracedExceptionInfo
{
int opApply( int delegate( inout char[] ) );
}
////////////////////////////////////////////////////////////////////////////////
/*
- Exception
- OutOfMemoryException
- TracedException
- SwitchException
- AssertException
- ArrayBoundsException
- FinalizeException
- PlatformException
- ProcessException
- ThreadException
- FiberException
- SyncException
- IOException
- SocketException
- SocketAcceptException
- AddressException
- HostException
- VfsException
- ClusterException
- NoSuchElementException
- CorruptedIteratorException
- IllegalArgumentException
- IllegalElementException
- TextException
- RegexException
- LocaleException
- UnicodeException
- PayloadException
*/
////////////////////////////////////////////////////////////////////////////////
/**
* Thrown on an out of memory error.
*/
class OutOfMemoryException : Exception
{
this( char[] file, size_t line )
{
super( "Memory allocation failed", file, line );
}
char[] toString()
{
return msg ? super.toString() : "Memory allocation failed";
}
}
/**
* Stores a stack trace when thrown.
*/
class TracedException : Exception
{
this( char[] msg )
{
super( msg );
m_info = traceContext();
}
this( char[] msg, Exception e )
{
super( msg, e );
m_info = traceContext();
}
this( char[] msg, char[] file, size_t line )
{
super( msg, file, line );
m_info = traceContext();
}
char[] toString()
{
if( m_info is null )
return super.toString();
char[] buf = super.toString();
buf ~= "\n----------------";
foreach( line; m_info )
buf ~= "\n" ~ line;
return buf;
}
int opApply( int delegate( inout char[] buf ) dg )
{
if( m_info is null )
return 0;
return m_info.opApply( dg );
}
private:
TracedExceptionInfo m_info;
}
/**
* Base class for operating system or library exceptions.
*/
class PlatformException : TracedException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Thrown on an assert error.
*/
class AssertException : TracedException
{
this( char[] file, size_t line )
{
super( "Assertion failure", file, line );
}
this( char[] msg, char[] file, size_t line )
{
super( msg, file, line );
}
}
/**
* Thrown on an array bounds error.
*/
class ArrayBoundsException : TracedException
{
this( char[] file, size_t line )
{
super( "Array index out of bounds", file, line );
}
}
/**
* Thrown on finalize error.
*/
class FinalizeException : TracedException
{
ClassInfo info;
this( ClassInfo c, Exception e = null )
{
super( "Finalization error", e );
info = c;
}
char[] toString()
{
//return "An exception was thrown while finalizing an instance of class " ~ info.name;
assert(0);
}
}
/**
* Thrown on a switch error.
*/
class SwitchException : TracedException
{
this( char[] file, size_t line )
{
super( "No appropriate switch clause found", file, line );
}
}
/**
* Represents a text processing error.
*/
class TextException : TracedException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Thrown on a unicode conversion error.
*/
class UnicodeException : TextException
{
size_t idx;
this( char[] msg, size_t idx )
{
super( msg );
this.idx = idx;
}
}
/**
* Base class for thread exceptions.
*/
class ThreadException : PlatformException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Base class for fiber exceptions.
*/
class FiberException : ThreadException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Base class for synchronization exceptions.
*/
class SyncException : PlatformException
{
this( char[] msg )
{
super( msg );
}
}
/**
* The basic exception thrown by the tango.io package. One should try to ensure
* that all Tango exceptions related to IO are derived from this one.
*/
class IOException : PlatformException
{
this( char[] msg )
{
super( msg );
}
}
/**
* The basic exception thrown by the tango.io.vfs package.
*/
private class VfsException : IOException
{
this( char[] msg )
{
super( msg );
}
}
/**
* The basic exception thrown by the tango.io.cluster package.
*/
private class ClusterException : IOException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Base class for socket exceptions.
*/
class SocketException : IOException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Base class for exception thrown by an InternetHost.
*/
class HostException : IOException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Base class for exceptiond thrown by an Address.
*/
class AddressException : IOException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Thrown when a socket failed to accept an incoming connection.
*/
class SocketAcceptException : SocketException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Thrown on a process error.
*/
class ProcessException : PlatformException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Base class for regluar expression exceptions.
*/
class RegexException : TextException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Base class for locale exceptions.
*/
class LocaleException : TextException
{
this( char[] msg )
{
super( msg );
}
}
/**
* RegistryException is thrown when the NetworkRegistry encounters a
* problem during proxy registration, or when it sees an unregistered
* guid.
*/
class RegistryException : TracedException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Thrown when an illegal argument is encountered.
*/
class IllegalArgumentException : TracedException
{
this( char[] msg )
{
super( msg );
}
}
/**
*
* IllegalElementException is thrown by Collection methods
* that add (or replace) elements (and/or keys) when their
* arguments are null or do not pass screeners.
*
*/
class IllegalElementException : IllegalArgumentException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Thrown on past-the-end errors by iterators and containers.
*/
class NoSuchElementException : TracedException
{
this( char[] msg )
{
super( msg );
}
}
/**
* Thrown when a corrupt iterator is detected.
*/
class CorruptedIteratorException : NoSuchElementException
{
this( char[] msg )
{
super( msg );
}
}
////////////////////////////////////////////////////////////////////////////////
// Overrides
////////////////////////////////////////////////////////////////////////////////
/**
* Overrides the default assert hander with a user-supplied version.
*
* Params:
* h = The new assert handler. Set to null to use the default handler.
*/
void setAssertHandler( assertHandlerType h )
{
assertHandler = h;
}
/**
* Overrides the default trace hander with a user-supplied version.
*
* Params:
* h = The new trace handler. Set to null to use the default handler.
*/
void setTraceHandler( traceHandlerType h )
{
traceHandler = h;
}
////////////////////////////////////////////////////////////////////////////////
// Overridable Callbacks
////////////////////////////////////////////////////////////////////////////////
/**
* A callback for assert errors in D. The user-supplied assert handler will
* be called if one has been supplied, otherwise an AssertException will be
* thrown.
*
* Params:
* file = The name of the file that signaled this error.
* line = The line number on which this error occurred.
*/
extern (C) void onAssertError( char[] file, size_t line )
{
if( assertHandler is null )
throw new AssertException( file, line );
assertHandler( file, line );
}
/**
* A callback for assert errors in D. The user-supplied assert handler will
* be called if one has been supplied, otherwise an AssertException will be
* thrown.
*
* Params:
* file = The name of the file that signaled this error.
* line = The line number on which this error occurred.
* msg = An error message supplied by the user.
*/
extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg )
{
if( assertHandler is null )
throw new AssertException( msg, file, line );
assertHandler( file, line, msg );
}
/**
* This function will be called when a TracedException is constructed. The
* user-supplied trace handler will be called if one has been supplied,
* otherwise no trace will be generated.
*
* Params:
* ptr = A pointer to the location from which to generate the trace, or null
* if the trace should be generated from within the trace handler
* itself.
*
* Returns:
* An object describing the current calling context or null if no handler is
* supplied.
*/
TracedExceptionInfo traceContext( void* ptr = null )
{
if( traceHandler is null )
return null;
return traceHandler( ptr );
}
////////////////////////////////////////////////////////////////////////////////
// Internal Error Callbacks
////////////////////////////////////////////////////////////////////////////////
/**
* A callback for array bounds errors in D. An ArrayBoundsException will be
* thrown.
*
* Params:
* file = The name of the file that signaled this error.
* line = The line number on which this error occurred.
*
* Throws:
* ArrayBoundsException.
*/
extern (C) void onArrayBoundsError( char[] file, size_t line )
{
throw new ArrayBoundsException( file, line );
}
/**
* A callback for finalize errors in D. A FinalizeException will be thrown.
*
* Params:
* e = The exception thrown during finalization.
*
* Throws:
* FinalizeException.
*/
extern (C) void onFinalizeError( ClassInfo info, Exception ex )
{
throw new FinalizeException( info, ex );
}
/**
* A callback for out of memory errors in D. An OutOfMemoryException will be
* thrown.
*
* Throws:
* OutOfMemoryException.
*/
extern (C) void onOutOfMemoryError()
{
// NOTE: Since an out of memory condition exists, no allocation must occur
// while generating this object.
throw cast(OutOfMemoryException) cast(void*) OutOfMemoryException.classinfo.init;
}
/**
* A callback for switch errors in D. A SwitchException will be thrown.
*
* Params:
* file = The name of the file that signaled this error.
* line = The line number on which this error occurred.
*
* Throws:
* SwitchException.
*/
extern (C) void onSwitchError( char[] file, size_t line )
{
throw new SwitchException( file, line );
}
/**
* A callback for unicode errors in D. A UnicodeException will be thrown.
*
* Params:
* msg = Information about the error.
* idx = String index where this error was detected.
*
* Throws:
* UnicodeException.
*/
extern (C) void onUnicodeError( char[] msg, size_t idx )
{
throw new UnicodeException( msg, idx );
}
+458
View File
@@ -0,0 +1,458 @@
/**
* The memory module provides an interface to the garbage collector and to
* any other OS or API-level memory management facilities.
*
* Copyright: Copyright (C) 2005-2006 Sean Kelly. All rights reserved.
* License: BSD style: $(LICENSE)
* Authors: Sean Kelly
*/
module tango.core.Memory;
private
{
extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void gc_enable();
extern (C) void gc_disable();
extern (C) void gc_collect();
extern (C) uint gc_getAttr( void* p );
extern (C) uint gc_setAttr( void* p, uint a );
extern (C) uint gc_clrAttr( void* p, uint a );
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0 );
extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
extern (C) void gc_free( void* p );
extern (C) void* gc_addrOf( void* p );
extern (C) size_t gc_sizeOf( void* p );
struct BlkInfo_
{
void* base;
size_t size;
uint attr;
}
extern (C) BlkInfo_ gc_query( void* p );
extern (C) void gc_addRoot( void* p );
extern (C) void gc_addRange( void* p, size_t sz );
extern (C) void gc_removeRoot( void* p );
extern (C) void gc_removeRange( void* p );
alias bool function( Object obj ) collectHandlerType;
}
/**
* This struct encapsulates all garbage collection functionality for the D
* programming language.
*/
struct GC
{
/**
* Enables the garbage collector if collections have previously been
* suspended by a call to disable. This function is reentrant, and
* must be called once for every call to disable before the garbage
* collector is enabled.
*/
static void enable()
{
gc_enable();
}
/**
* Disables the garbage collector. This function is reentrant, but
* enable must be called once for each call to disable.
*/
static void disable()
{
gc_disable();
}
/**
* Begins a full collection. While the meaning of this may change based
* on the garbage collector implementation, typical behavior is to scan
* all stack segments for roots, mark accessible memory blocks as alive,
* and then to reclaim free space. This action may need to suspend all
* running threads for at least part of the collection process.
*/
static void collect()
{
gc_collect();
}
/**
* Elements for a bit field representing memory block attributes. These
* are manipulated via the getAttr, setAttr, clrAttr functions.
*/
enum BlkAttr : uint
{
FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect.
NO_SCAN = 0b0000_0010, /// Do not scan through this block on collect.
NO_MOVE = 0b0000_0100 /// Do not move this memory block on collect.
}
/**
* Contains aggregate information about a block of managed memory. The
* purpose of this struct is to support a more efficient query style in
* instances where detailed information is needed.
*
* base = A pointer to the base of the block in question.
* size = The size of the block, calculated from base.
* attr = Attribute bits set on the memory block.
*/
alias BlkInfo_ BlkInfo;
/**
* Returns a bit field representing all block attributes set for the memory
* referenced by p. If p references memory not originally allocated by this
* garbage collector, points to the interior of a memory block, or if p is
* null, zero will be returned.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
*
* Returns:
* A bit field containing any bits set for the memory block referenced by
* p or zero on error.
*/
static uint getAttr( void* p )
{
return gc_getAttr( p );
}
/**
* Sets the specified bits for the memory references by p. If p references
* memory not originally allocated by this garbage collector, points to the
* interior of a memory block, or if p is null, no action will be performed.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
* a = A bit field containing any bits to set for this memory block.
*
* The result of a call to getAttr after the specified bits have been
* set.
*/
static uint setAttr( void* p, uint a )
{
return gc_setAttr( p, a );
}
/**
* Clears the specified bits for the memory references by p. If p
* references memory not originally allocated by this garbage collector,
* points to the interior of a memory block, or if p is null, no action
* will be performed.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
* a = A bit field containing any bits to clear for this memory block.
*
* Returns:
* The result of a call to getAttr after the specified bits have been
* cleared.
*/
static uint clrAttr( void* p, uint a )
{
return gc_clrAttr( p, a );
}
/**
* Requests an aligned block of managed memory from the garbage collector.
* This memory may be deleted at will with a call to free, or it may be
* discarded and cleaned up automatically during a collection run. If
* allocation fails, this function will call onOutOfMemory which is
* expected to throw an OutOfMemoryException.
*
* Params:
* sz = The desired allocation size in bytes.
* ba = A bitmask of the attributes to set on this block.
*
* Returns:
* A reference to the allocated memory or null if insufficient memory
* is available.
*
* Throws:
* OutOfMemoryException on allocation failure.
*/
static void* malloc( size_t sz, uint ba = 0 )
{
return gc_malloc( sz, ba );
}
/**
* Requests an aligned block of managed memory from the garbage collector,
* which is initialized with all bits set to zero. This memory may be
* deleted at will with a call to free, or it may be discarded and cleaned
* up automatically during a collection run. If allocation fails, this
* function will call onOutOfMemory which is expected to throw an
* OutOfMemoryException.
*
* Params:
* sz = The desired allocation size in bytes.
* ba = A bitmask of the attributes to set on this block.
*
* Returns:
* A reference to the allocated memory or null if insufficient memory
* is available.
*
* Throws:
* OutOfMemoryException on allocation failure.
*/
static void* calloc( size_t sz, uint ba = 0 )
{
return gc_calloc( sz, ba );
}
/**
* If sz is zero, the memory referenced by p will be deallocated as if
* by a call to free. A new memory block of size sz will then be
* allocated as if by a call to malloc, or the implementation may instead
* resize the memory block in place. The contents of the new memory block
* will be the same as the contents of the old memory block, up to the
* lesser of the new and old sizes. Note that existing memory will only
* be freed by realloc if sz is equal to zero. The garbage collector is
* otherwise expected to later reclaim the memory block if it is unused.
* If allocation fails, this function will call onOutOfMemory which is
* expected to throw an OutOfMemoryException. If p references memory not
* originally allocated by this garbage collector, or if it points to the
* interior of a memory block, no action will be taken. If ba is zero
* (the default) and p references the head of a valid, known memory block
* then any bits set on the current block will be set on the new block if a
* reallocation is required. If ba is not zero and p references the head
* of a valid, known memory block then the bits in ba will replace those on
* the current memory block and will also be set on the new block if a
* reallocation is required.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
* sz = The desired allocation size in bytes.
* ba = A bitmask of the attributes to set on this block.
*
* Returns:
* A reference to the allocated memory on success or null if sz is
* zero. On failure, the original value of p is returned.
*
* Throws:
* OutOfMemoryException on allocation failure.
*/
static void* realloc( void* p, size_t sz, uint ba = 0 )
{
return gc_realloc( p, sz, ba );
}
/**
* Requests that the managed memory block referenced by p be extended in
* place by at least mx bytes, with a desired extension of sz bytes. If an
* extension of the required size is not possible, if p references memory
* not originally allocated by this garbage collector, or if p points to
* the interior of a memory block, no action will be taken.
*
* Params:
* mx = The minimum extension size in bytes.
* sz = The desired extension size in bytes.
*
* Returns:
* The size in bytes of the extended memory block referenced by p or zero
* if no extension occurred.
*/
static size_t extend( void* p, size_t mx, size_t sz )
{
return gc_extend( p, mx, sz );
}
/**
* Deallocates the memory referenced by p. If p is null, no action
* occurs. If p references memory not originally allocated by this
* garbage collector, or if it points to the interior of a memory block,
* no action will be taken. The block will not be finalized regardless
* of whether the FINALIZE attribute is set. If finalization is desired,
* use delete instead.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
*/
static void free( void* p )
{
gc_free( p );
}
/**
* Returns the base address of the memory block containing p. This value
* is useful to determine whether p is an interior pointer, and the result
* may be passed to routines such as sizeOf which may otherwise fail. If p
* references memory not originally allocated by this garbage collector, if
* p is null, or if the garbage collector does not support this operation,
* null will be returned.
*
* Params:
* p = A pointer to the root or the interior of a valid memory block or to
* null.
*
* Returns:
* The base address of the memory block referenced by p or null on error.
*/
static void* addrOf( void* p )
{
return gc_addrOf( p );
}
/**
* Returns the true size of the memory block referenced by p. This value
* represents the maximum number of bytes for which a call to realloc may
* resize the existing block in place. If p references memory not
* originally allocated by this garbage collector, points to the interior
* of a memory block, or if p is null, zero will be returned.
*
* Params:
* p = A pointer to the root of a valid memory block or to null.
*
* Returns:
* The size in bytes of the memory block referenced by p or zero on error.
*/
static size_t sizeOf( void* p )
{
return gc_sizeOf( p );
}
/**
* Returns aggregate information about the memory block containing p. If p
* references memory not originally allocated by this garbage collector, if
* p is null, or if the garbage collector does not support this operation,
* BlkInfo.init will be returned. Typically, support for this operation
* is dependent on support for addrOf.
*
* Params:
* p = A pointer to the root or the interior of a valid memory block or to
* null.
*
* Returns:
* Information regarding the memory block referenced by p or BlkInfo.init
* on error.
*/
static BlkInfo query( void* p )
{
return gc_query( p );
}
/**
* Adds the memory address referenced by p to an internal list of roots to
* be scanned during a collection. If p is null, no operation is
* performed.
*
* Params:
* p = A pointer to a valid memory address or to null.
*/
static void addRoot( void* p )
{
gc_addRoot( p );
}
/**
* Adds the memory block referenced by p and of size sz to an internal list
* of ranges to be scanned during a collection. If p is null, no operation
* is performed.
*
* Params:
* p = A pointer to a valid memory address or to null.
* sz = The size in bytes of the block to add. If sz is zero then the
* no operation will occur. If p is null then sz must be zero.
*/
static void addRange( void* p, size_t sz )
{
gc_addRange( p, sz );
}
/**
* Removes the memory block referenced by p from an internal list of roots
* to be scanned during a collection. If p is null or does not represent
* a value previously passed to add(void*) then no operation is performed.
*
* p = A pointer to a valid memory address or to null.
*/
static void removeRoot( void* p )
{
gc_removeRoot( p );
}
/**
* Removes the memory block referenced by p from an internal list of ranges
* to be scanned during a collection. If p is null or does not represent
* a value previously passed to add(void*, size_t) then no operation is
* performed.
*
* Params:
* p = A pointer to a valid memory address or to null.
*/
static void removeRange( void* p )
{
gc_removeRange( p );
}
/**
* Overrides the default collect hander with a user-supplied version.
*
* Params:
* h = The new collect handler. Set to null to use the default handler.
*/
static void collectHandler( collectHandlerType h )
{
sm_collectHandler = h;
}
private:
static collectHandlerType sm_collectHandler = null;
}
////////////////////////////////////////////////////////////////////////////////
// Overridable Callbacks
////////////////////////////////////////////////////////////////////////////////
/**
* This function will be called when resource objects (ie. objects with a dtor)
* are finalized by the garbage collector. The user-supplied collect handler
* will be called if one has been supplied, otherwise no action will be taken.
*
* Params:
* obj = The object being collected.
*
* Returns:
* true if the runtime should call this object's dtor and false if not.
* Default behavior is to return true.
*/
extern (C) bool onCollectResource( Object obj )
{
if( GC.sm_collectHandler is null )
return true;
return GC.sm_collectHandler( obj );
}
+87
View File
@@ -0,0 +1,87 @@
/**
* The runtime module exposes information specific to the D runtime code.
*
* Copyright: Copyright (C) 2005-2006 Sean Kelly. All rights reserved.
* License: BSD style: $(LICENSE)
* Authors: Sean Kelly
*/
module tango.core.Runtime;
private
{
extern (C) bool rt_isHalting();
alias bool function() moduleUnitTesterType;
}
////////////////////////////////////////////////////////////////////////////////
// Runtime
////////////////////////////////////////////////////////////////////////////////
/**
* This struct encapsulates all functionality related to the underlying runtime
* module for the calling context.
*/
struct Runtime
{
/**
* Returns true if the runtime is halting. Under normal circumstances,
* this will be set between the time that normal application code has
* exited and before module dtors are called.
*
* Returns:
* true if the runtime is halting.
*/
static bool isHalting()
{
return rt_isHalting();
}
/**
* Overrides the default module unit tester with a user-supplied version.
*
* Params:
* h = The new unit tester. Set to null to use the default unit tester.
*/
static void moduleUnitTester( moduleUnitTesterType h )
{
sm_moduleUnitTester = h;
}
private:
static moduleUnitTesterType sm_moduleUnitTester = null;
}
////////////////////////////////////////////////////////////////////////////////
// Overridable Callbacks
////////////////////////////////////////////////////////////////////////////////
/**
* This routine is called by the runtime to run module unit tests on startup.
* The user-supplied unit tester will be called if one has been supplied,
* otherwise all unit tests will be run in sequence.
*
* Returns:
* true if execution should continue after testing is complete and false if
* not. Default behavior is to return true.
*/
extern (C) bool runModuleUnitTests()
{
if( Runtime.sm_moduleUnitTester is null )
{
foreach( m; ModuleInfo )
{
if( m.unitTest )
m.unitTest();
}
return true;
}
return Runtime.sm_moduleUnitTester();
}
File diff suppressed because it is too large Load Diff
+136
View File
@@ -0,0 +1,136 @@
/**
* Tango Fiber switching assembler code.
*
* Author: Mikola Lysenko
*/
/************************************************************************************
* POWER PC ASM BITS
************************************************************************************/
#if defined( __ppc__ ) || defined( __PPC__ ) || defined( __powerpc__ )
/**
* Performs a context switch.
*
* r3 - old context pointer
* r4 - new context pointer
*
*/
.text
.align 2
.globl _fiber_switchContext
_fiber_switchContext:
/* Save linkage area */
mflr r0
mfcr r5
stw r0, 8(r1)
stw r5, 4(r1)
/* Save GPRs */
stw r11, (-1 * 4)(r1)
stw r13, (-2 * 4)(r1)
stw r14, (-3 * 4)(r1)
stw r15, (-4 * 4)(r1)
stw r16, (-5 * 4)(r1)
stw r17, (-6 * 4)(r1)
stw r18, (-7 * 4)(r1)
stw r19, (-8 * 4)(r1)
stw r20, (-9 * 4)(r1)
stw r21, (-10 * 4)(r1)
stw r22, (-11 * 4)(r1)
stw r23, (-12 * 4)(r1)
stw r24, (-13 * 4)(r1)
stw r25, (-14 * 4)(r1)
stw r26, (-15 * 4)(r1)
stw r27, (-16 * 4)(r1)
stw r28, (-17 * 4)(r1)
stw r29, (-18 * 4)(r1)
stw r30, (-19 * 4)(r1)
stwu r31, (-20 * 4)(r1)
/* We update the stack pointer here, since we do not want the GC to
scan the floating point registers. */
/* Save FPRs */
stfd f14, (-1 * 8)(r1)
stfd f15, (-2 * 8)(r1)
stfd f16, (-3 * 8)(r1)
stfd f17, (-4 * 8)(r1)
stfd f18, (-5 * 8)(r1)
stfd f19, (-6 * 8)(r1)
stfd f20, (-7 * 8)(r1)
stfd f21, (-8 * 8)(r1)
stfd f22, (-9 * 8)(r1)
stfd f23, (-10 * 8)(r1)
stfd f24, (-11 * 8)(r1)
stfd f25, (-12 * 8)(r1)
stfd f26, (-13 * 8)(r1)
stfd f27, (-14 * 8)(r1)
stfd f28, (-15 * 8)(r1)
stfd f29, (-16 * 8)(r1)
stfd f30, (-17 * 8)(r1)
stfd f31, (-18 * 8)(r1)
/* Update the old stack pointer */
stw r1, 0(r3)
/* Set new stack pointer */
addi r1, r4, 20 * 4
/* Restore linkage area */
lwz r0, 8(r1)
lwz r5, 4(r1)
/* Restore GPRs */
lwz r11, (-1 * 4)(r1)
lwz r13, (-2 * 4)(r1)
lwz r14, (-3 * 4)(r1)
lwz r15, (-4 * 4)(r1)
lwz r16, (-5 * 4)(r1)
lwz r17, (-6 * 4)(r1)
lwz r18, (-7 * 4)(r1)
lwz r19, (-8 * 4)(r1)
lwz r20, (-9 * 4)(r1)
lwz r21, (-10 * 4)(r1)
lwz r22, (-11 * 4)(r1)
lwz r23, (-12 * 4)(r1)
lwz r24, (-13 * 4)(r1)
lwz r25, (-14 * 4)(r1)
lwz r26, (-15 * 4)(r1)
lwz r27, (-16 * 4)(r1)
lwz r28, (-17 * 4)(r1)
lwz r29, (-18 * 4)(r1)
lwz r30, (-19 * 4)(r1)
lwz r31, (-20 * 4)(r1)
/* Restore FPRs */
lfd f14, (-1 * 8)(r4)
lfd f15, (-2 * 8)(r4)
lfd f16, (-3 * 8)(r4)
lfd f17, (-4 * 8)(r4)
lfd f18, (-5 * 8)(r4)
lfd f19, (-6 * 8)(r4)
lfd f20, (-7 * 8)(r4)
lfd f21, (-8 * 8)(r4)
lfd f22, (-9 * 8)(r4)
lfd f23, (-10 * 8)(r4)
lfd f24, (-11 * 8)(r4)
lfd f25, (-12 * 8)(r4)
lfd f26, (-13 * 8)(r4)
lfd f27, (-14 * 8)(r4)
lfd f28, (-15 * 8)(r4)
lfd f29, (-16 * 8)(r4)
lfd f30, (-17 * 8)(r4)
lfd f31, (-18 * 8)(r4)
/* Set condition and link register */
mtcr r5
mtlr r0
/* Return and switch context */
blr
#endif
+139
View File
@@ -0,0 +1,139 @@
# Makefile to build the common D runtime library for LLVM
# Designed to work with GNU make
# Targets:
# make
# Same as make all
# make lib
# Build the common library
# make doc
# Generate documentation
# make clean
# Delete unneeded files created by build process
LIB_TARGET=libtango-cc-tango.a
LIB_MASK=libtango-cc-tango*.a
CP=cp -f
RM=rm -f
MD=mkdir -p
ADD_CFLAGS=
ADD_DFLAGS=
CFLAGS=-O $(ADD_CFLAGS)
#CFLAGS=-g $(ADD_CFLAGS)
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
DOCFLAGS=-version=DDoc
CC=gcc
LC=llvm-ar rsv
DC=llvmdc
LLC=llvm-as
INC_DEST=../../../tango
LIB_DEST=..
DOC_DEST=../../../doc/tango
.SUFFIXES: .s .S .c .cpp .d .ll .html .o .bc
.s.o:
$(CC) -c $(CFLAGS) $< -o$@
.S.o:
$(CC) -c $(CFLAGS) $< -o$@
.c.o:
$(CC) -c $(CFLAGS) $< -o$@
.cpp.o:
g++ -c $(CFLAGS) $< -o$@
.d.bc:
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
# $(DC) -c $(DFLAGS) $< -of$@
.ll.bc:
$(LLC) -f -o=$@ $<
.d.html:
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
# $(DC) -c -o- $(DOCFLAGS) -Df$*.html tango.ddoc $<
targets : lib doc
all : lib doc
tango : lib
lib : tango.lib
doc : tango.doc
######################################################
OBJ_CORE= \
core/BitManip.bc \
core/Exception.bc \
core/Memory.bc \
core/Runtime.bc \
core/Thread.bc
# core/ThreadASM.o
OBJ_STDC= \
stdc/wrap.bc
OBJ_STDC_POSIX= \
stdc/posix/pthread_darwin.o
ALL_OBJS= \
$(OBJ_CORE) \
$(OBJ_STDC)
# $(OBJ_STDC_POSIX)
######################################################
DOC_CORE= \
core/BitManip.html \
core/Exception.html \
core/Memory.html \
core/Runtime.html \
core/Thread.html
ALL_DOCS=
######################################################
tango.lib : $(LIB_TARGET)
$(LIB_TARGET) : $(ALL_OBJS)
$(RM) $@
$(LC) $@ $(ALL_OBJS)
tango.doc : $(ALL_DOCS)
echo Documentation generated.
######################################################
### stdc/posix
#stdc/posix/pthread_darwin.o : stdc/posix/pthread_darwin.d
# $(DC) -c $(DFLAGS) stdc/posix/pthread_darwin.d -of$@
######################################################
clean :
find . -name "*.di" | xargs $(RM)
$(RM) $(ALL_OBJS)
$(RM) $(ALL_DOCS)
find . -name "$(LIB_MASK)" | xargs $(RM)
install :
$(MD) $(INC_DEST)
find . -name "*.di" -exec cp -f {} $(INC_DEST)/{} \;
$(MD) $(DOC_DEST)
find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \;
$(MD) $(LIB_DEST)
find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \;
+135
View File
@@ -0,0 +1,135 @@
# Makefile to build the common D runtime library for Linux
# Designed to work with GNU make
# Targets:
# make
# Same as make all
# make lib
# Build the common library
# make doc
# Generate documentation
# make clean
# Delete unneeded files created by build process
LIB_TARGET=libtango-cc-tango.a
LIB_MASK=libtango-cc-tango*.a
CP=cp -f
RM=rm -f
MD=mkdir -p
ADD_CFLAGS=
ADD_DFLAGS=
CFLAGS=-O -m32 $(ADD_CFLAGS)
#CFLAGS=-g -m32 $(ADD_CFLAGS)
DFLAGS=-release -O -inline -w -nofloat -version=Posix $(ADD_DFLAGS)
#DFLAGS=-g -w -nofloat -version=Posix $(ADD_DFLAGS)
TFLAGS=-O -inline -w -nofloat -version=Posix $(ADD_DFLAGS)
#TFLAGS=-g -w -nofloat -version=Posix $(ADD_DFLAGS)
DOCFLAGS=-version=DDoc -version=Posix
CC=gcc
LC=$(AR) -qsv
DC=dmd
INC_DEST=../../../tango
LIB_DEST=..
DOC_DEST=../../../doc/tango
.SUFFIXES: .s .S .c .cpp .d .html .o
.s.o:
$(CC) -c $(CFLAGS) $< -o$@
.S.o:
$(CC) -c $(CFLAGS) $< -o$@
.c.o:
$(CC) -c $(CFLAGS) $< -o$@
.cpp.o:
g++ -c $(CFLAGS) $< -o$@
.d.o:
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
# $(DC) -c $(DFLAGS) $< -of$@
.d.html:
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
# $(DC) -c -o- $(DOCFLAGS) -Df$*.html tango.ddoc $<
targets : lib doc
all : lib doc
tango : lib
lib : tango.lib
doc : tango.doc
######################################################
OBJ_CORE= \
core/BitManip.o \
core/Exception.o \
core/Memory.o \
core/Runtime.o \
core/Thread.o \
core/ThreadASM.o
OBJ_STDC= \
stdc/wrap.o
OBJ_STDC_POSIX= \
stdc/posix/pthread_darwin.o
ALL_OBJS= \
$(OBJ_CORE) \
$(OBJ_STDC) \
$(OBJ_STDC_POSIX)
######################################################
DOC_CORE= \
core/BitManip.html \
core/Exception.html \
core/Memory.html \
core/Runtime.html \
core/Thread.html
ALL_DOCS=
######################################################
tango.lib : $(LIB_TARGET)
$(LIB_TARGET) : $(ALL_OBJS)
$(RM) $@
$(LC) $@ $(ALL_OBJS)
tango.doc : $(ALL_DOCS)
echo Documentation generated.
######################################################
### stdc/posix
stdc/posix/pthread_darwin.o : stdc/posix/pthread_darwin.d
$(DC) -c $(DFLAGS) stdc/posix/pthread_darwin.d -of$@
######################################################
clean :
find . -name "*.di" | xargs $(RM)
$(RM) $(ALL_OBJS)
$(RM) $(ALL_DOCS)
find . -name "$(LIB_MASK)" | xargs $(RM)
install :
$(MD) $(INC_DEST)
find . -name "*.di" -exec cp -f {} $(INC_DEST)/{} \;
$(MD) $(DOC_DEST)
find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \;
$(MD) $(LIB_DEST)
find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \;
@@ -0,0 +1,334 @@
/**
* D header file for POSIX.
*
* Copyright: Public Domain
* License: Public Domain
* Authors: Sean Kelly
* Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
*/
module tango.stdc.posix.pthread;
public import tango.stdc.posix.sys.types;
public import tango.stdc.posix.sched;
public import tango.stdc.posix.time;
private import tango.stdc.stdlib;
extern (C):
//
// Required
//
version( darwin )
{
int pthread_cond_broadcast(pthread_cond_t*);
int pthread_cond_destroy(pthread_cond_t*);
int pthread_cond_init(pthread_cond_t*, pthread_condattr_t*);
//int pthread_cond_signal(pthread_cond_t*);
//int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, timespec*);
int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*);
int pthread_mutex_destroy(pthread_mutex_t*);
int pthread_mutex_init(pthread_mutex_t*, pthread_mutexattr_t*);
int pthread_mutex_lock(pthread_mutex_t*);
int pthread_mutex_trylock(pthread_mutex_t*);
int pthread_mutex_unlock(pthread_mutex_t*);
//int pthread_rwlock_destroy(pthread_rwlock_t*);
//int pthread_rwlock_init(pthread_rwlock_t*, pthread_rwlockattr_t*);
//int pthread_rwlock_rdlock(pthread_rwlock_t*);
int pthread_rwlock_tryrdlock(pthread_rwlock_t*);
int pthread_rwlock_trywrlock(pthread_rwlock_t*);
//int pthread_rwlock_unlock(pthread_rwlock_t*);
//int pthread_rwlock_wrlock(pthread_rwlock_t*);
}
//
// Barrier (BAR)
//
/*
PTHREAD_BARRIER_SERIAL_THREAD
int pthread_barrier_destroy(pthread_barrier_t*);
int pthread_barrier_init(pthread_barrier_t*, pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
int pthread_barrierattr_getpshared(pthread_barrierattr_t*, int*); (BAR|TSH)
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); (BAR|TSH)
*/
version( darwin )
{
const PTHREAD_BARRIER_SERIAL_THREAD = -1;
// defined in tango.stdc.posix.pthread and redefined here
enum
{
PTHREAD_PROCESS_PRIVATE,
PTHREAD_PROCESS_SHARED
}
int pthread_barrier_destroy( pthread_barrier_t* barrier )
{
if( barrier is null )
return EINVAL;
if( barrier.b_waiters > 0 )
return EBUSY;
int mret = pthread_mutex_destroy( &barrier.b_lock );
int cret = pthread_cond_destroy( &barrier.b_cond );
free( barrier );
return mret ? mret : cret;
}
int pthread_barrier_init( pthread_barrier_t* barrier,
pthread_barrierattr_t* attr,
uint count )
{
if( barrier is null || count <= 0 )
return EINVAL;
pthread_barrier_t* newbarrier = cast(pthread_barrier_t*)
malloc( pthread_barrier_t.sizeof );
if( newbarrier is null )
return ENOMEM;
int ret;
if( ( ret = pthread_mutex_init( &newbarrier.b_lock, null ) ) != 0 )
{
free( newbarrier );
return ret;
}
if( ( ret = pthread_cond_init( &newbarrier.b_cond, null ) ) != 0 )
{
pthread_mutex_destroy( &newbarrier.b_lock );
free( newbarrier );
return ret;
}
newbarrier.b_waiters = 0;
newbarrier.b_count = count;
newbarrier.b_generation = 0;
*barrier = *newbarrier;
return 0;
}
int pthread_barrier_wait( pthread_barrier_t* barrier )
{
if( barrier is null )
return EINVAL;
int ret;
if( ( ret = pthread_mutex_lock( &barrier.b_lock ) ) != 0 )
return ret;
if( ++barrier.b_waiters == barrier.b_count )
{
// current thread is lastest thread
barrier.b_generation++;
barrier.b_waiters = 0;
if( ( ret = pthread_cond_broadcast( &barrier.b_cond ) ) == 0 )
ret = PTHREAD_BARRIER_SERIAL_THREAD;
}
else
{
int gen = barrier.b_generation;
do
{
ret = pthread_cond_wait( &barrier.b_cond, &barrier.b_lock );
// test generation to avoid bogus wakeup
} while( ret == 0 && gen == barrier.b_generation );
}
pthread_mutex_unlock( &barrier.b_lock );
return ret;
}
int pthread_barrierattr_destroy( pthread_barrierattr_t* attr )
{
if( attr is null )
return EINVAL;
free( attr );
return 0;
}
int pthread_barrierattr_getpshared( pthread_barrierattr_t* attr, int* pshared )
{
if( attr is null )
return EINVAL;
*pshared = attr.pshared;
return 0;
}
int pthread_barrierattr_init( pthread_barrierattr_t* attr )
{
if( attr is null )
return EINVAL;
if( ( attr = cast(pthread_barrierattr_t*)
malloc( pthread_barrierattr_t.sizeof ) ) is null )
return ENOMEM;
attr.pshared = PTHREAD_PROCESS_PRIVATE;
return 0;
}
int pthread_barrierattr_setpshared( pthread_barrierattr_t* attr, int pshared )
{
if( attr is null )
return EINVAL;
// only PTHREAD_PROCESS_PRIVATE is supported
if( pshared != PTHREAD_PROCESS_PRIVATE )
return EINVAL;
attr.pshared = pshared;
return 0;
}
}
//
// Timeouts (TMO)
//
/*
int pthread_mutex_timedlock(pthread_mutex_t*, timespec*);
int pthread_rwlock_timedrdlock(pthread_rwlock_t*, timespec*);
int pthread_rwlock_timedwrlock(pthread_rwlock_t*, timespec*);
*/
version( darwin )
{
private
{
import tango.stdc.errno;
import tango.stdc.posix.unistd;
import tango.stdc.posix.sys.time;
extern (D)
{
void timerclear( timeval* tvp )
{
tvp.tv_sec = tvp.tv_usec = 0;
}
bool timerisset( timeval* tvp )
{
return tvp.tv_sec || tvp.tv_usec;
}
bool timer_cmp_leq( timeval* tvp, timeval* uvp )
{
return tvp.tv_sec == uvp.tv_sec ?
tvp.tv_usec <= uvp.tv_usec :
tvp.tv_sec <= uvp.tv_sec;
}
void timeradd( timeval* tvp, timeval* uvp, timeval* vvp )
{
vvp.tv_sec = tvp.tv_sec + uvp.tv_sec;
vvp.tv_usec = tvp.tv_usec + uvp.tv_usec;
if( vvp.tv_usec >= 1000000 )
{
vvp.tv_sec++;
vvp.tv_usec -= 1000000;
}
}
void timersub( timeval* tvp, timeval* uvp, timeval* vvp )
{
vvp.tv_sec = tvp.tv_sec - uvp.tv_sec;
vvp.tv_usec = tvp.tv_usec - uvp.tv_usec;
if( vvp.tv_usec < 0 )
{
vvp.tv_sec--;
vvp.tv_usec += 1000000;
}
}
void TIMEVAL_TO_TIMESPEC( timeval* tv, timespec* ts )
{
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
}
void TIMESPEC_TO_TIMEVAL( timeval* tv, timespec* ts )
{
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
}
}
}
int pthread_mutex_timedlock( pthread_mutex_t* m, timespec* t )
{
timeval currtime;
timeval maxwait;
TIMESPEC_TO_TIMEVAL( &maxwait, t );
timeval waittime;
waittime.tv_usec = 100;
while( timer_cmp_leq( &currtime, &maxwait ) )
{
int ret = pthread_mutex_trylock( m );
switch( ret )
{
case 0: // locked successfully
return ret;
case EBUSY: // waiting
timeradd( &currtime, &waittime, &currtime );
break;
default:
return ret;
}
usleep( waittime.tv_usec );
}
return ETIMEDOUT;
}
int pthread_rwlock_timedrdlock( pthread_rwlock_t *rwlock, timespec* t )
{
timeval currtime;
timeval maxwait;
TIMESPEC_TO_TIMEVAL( &maxwait, t );
timeval waittime;
waittime.tv_usec = 100;
while( timer_cmp_leq( &currtime, &maxwait ) )
{
int ret = pthread_rwlock_tryrdlock( rwlock );
switch( ret )
{
case 0: // locked successfully
return ret;
case EBUSY: // waiting
timeradd( &currtime, &waittime, &currtime );
break;
default:
return ret;
}
usleep( waittime.tv_usec );
}
return ETIMEDOUT;
}
int pthread_rwlock_timedwrlock( pthread_rwlock_t* l, timespec* t )
{
timeval currtime;
timeval maxwait;
TIMESPEC_TO_TIMEVAL( &maxwait, t );
timeval waittime;
waittime.tv_usec = 100;
while( timer_cmp_leq( &currtime, &maxwait ) )
{
int ret = pthread_rwlock_trywrlock( l );
switch( ret )
{
case 0: // locked successfully
return ret;
case EBUSY: // waiting
timeradd( &currtime, &waittime, &currtime );
break;
default:
return ret;
}
usleep( waittime.tv_usec );
}
return ETIMEDOUT;
}
}
+14
View File
@@ -0,0 +1,14 @@
#include <errno.h>
int getErrno()
{
return errno;
}
int setErrno( int val )
{
errno = val;
return val;
}
+14
View File
@@ -0,0 +1,14 @@
; ModuleID = 'wrap.bc'
@errno = external global i32 ; <i32*> [#uses=2]
define i32 @getErrno() {
entry:
%tmp = load i32* @errno ; <i32> [#uses=1]
ret i32 %tmp
}
define i32 @setErrno(i32 %val) {
entry:
store i32 %val, i32* @errno
ret i32 %val
}
+126
View File
@@ -0,0 +1,126 @@
# Makefile to build the common D runtime library for Win32
# Designed to work with DigitalMars make
# Targets:
# make
# Same as make all
# make lib
# Build the common library
# make doc
# Generate documentation
# make clean
# Delete unneeded files created by build process
LIB_TARGET=tango-cc-tango.lib
LIB_MASK=tango-cc-tango*.lib
CP=xcopy /y
RM=del /f
MD=mkdir
ADD_CFLAGS=
ADD_DFLAGS=
CFLAGS=-mn -6 -r $(ADD_CFLAGS)
#CFLAGS=-g -mn -6 -r $(ADD_CFLAGS)
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
DOCFLAGS=-version=DDoc
CC=dmc
LC=lib
DC=dmd
INC_DEST=..\..\..\tango
LIB_DEST=..
DOC_DEST=..\..\..\doc\tango
.DEFAULT: .asm .c .cpp .d .html .obj
.asm.obj:
$(CC) -c $<
.c.obj:
$(CC) -c $(CFLAGS) $< -o$@
.cpp.obj:
$(CC) -c $(CFLAGS) $< -o$@
.d.obj:
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
# $(DC) -c $(DFLAGS) $< -of$@
.d.html:
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
# $(DC) -c -o- $(DOCFLAGS) -Df$*.html tango.ddoc $<
targets : lib doc
all : lib doc
tango : lib
lib : tango.lib
doc : tango.doc
######################################################
OBJ_CORE= \
core\BitManip.obj \
core\Exception.obj \
core\Memory.obj \
core\Runtime.obj \
core\Thread.obj
OBJ_STDC= \
stdc\wrap.obj
ALL_OBJS= \
$(OBJ_CORE) \
$(OBJ_STDC)
######################################################
DOC_CORE= \
core\BitManip.html \
core\Exception.html \
core\Memory.html \
core\Runtime.html \
core\Thread.html
ALL_DOCS=
######################################################
tango.lib : $(LIB_TARGET)
$(LIB_TARGET) : $(ALL_OBJS)
$(RM) $@
$(LC) -c -n $@ $(ALL_OBJS)
tango.doc : $(ALL_DOCS)
@echo Documentation generated.
######################################################
### config
# config.obj : config.d
# $(DC) -c $(DFLAGS) config.d -of$@
######################################################
clean :
$(RM) /s .\*.di
$(RM) $(ALL_OBJS)
$(RM) $(ALL_DOCS)
$(RM) $(LIB_MASK)
install :
$(MD) $(INC_DEST)
$(CP) /s *.di $(INC_DEST)\.
$(MD) $(DOC_DEST)
$(CP) /s *.html $(DOC_DEST)\.
$(MD) $(LIB_DEST)
$(CP) $(LIB_MASK) $(LIB_DEST)\.