mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-17 19:07:05 +02:00
[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:
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
@@ -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)/{} \;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
int getErrno()
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
int setErrno( int val )
|
||||
{
|
||||
errno = val;
|
||||
return val;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)\.
|
||||
Reference in New Issue
Block a user