Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 25 additions & 24 deletions src/core/memory.d
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ struct GC
* Pure variants of C's memory allocation functions `malloc`, `calloc`, and
* `realloc` and deallocation function `free`.
*
* UNIX 98 requires that errno be set to ENOMEM upon failure.
* Purity is achieved by saving and restoring the value of `errno`, thus
* behaving as if it were never changed.
*
Expand All @@ -823,42 +824,33 @@ struct GC
*/
void* pureMalloc(size_t size) @trusted pure @nogc nothrow
{
const errno = fakePureGetErrno();
const errnosave = fakePureErrno();
void* ret = fakePureMalloc(size);
if (!ret || errno != 0)
{
cast(void)fakePureSetErrno(errno);
}
fakePureErrno() = errnosave;
return ret;
}
/// ditto
void* pureCalloc(size_t nmemb, size_t size) @trusted pure @nogc nothrow
{
const errno = fakePureGetErrno();
const errnosave = fakePureErrno();
void* ret = fakePureCalloc(nmemb, size);
if (!ret || errno != 0)
{
cast(void)fakePureSetErrno(errno);
}
fakePureErrno() = errnosave;
return ret;
}
/// ditto
void* pureRealloc(void* ptr, size_t size) @system pure @nogc nothrow
{
const errno = fakePureGetErrno();
const errnosave = fakePureErrno();
void* ret = fakePureRealloc(ptr, size);
if (!ret || errno != 0)
{
cast(void)fakePureSetErrno(errno);
}
fakePureErrno() = errnosave;
return ret;
}
/// ditto
void pureFree(void* ptr) @system pure @nogc nothrow
{
const errno = fakePureGetErrno();
const errnosave = fakePureErrno();
fakePureFree(ptr);
cast(void)fakePureSetErrno(errno);
fakePureErrno() = errnosave;
}

///
Expand All @@ -881,36 +873,45 @@ void pureFree(void* ptr) @system pure @nogc nothrow

@system pure nothrow @nogc unittest
{
const int errno = fakePureGetErrno();
const int errno = fakePureErrno();

void* x = pureMalloc(10); // normal allocation
assert(errno == fakePureGetErrno()); // errno shouldn't change
assert(errno == fakePureErrno()); // errno shouldn't change
assert(x !is null); // allocation should succeed

x = pureRealloc(x, 10); // normal reallocation
assert(errno == fakePureGetErrno()); // errno shouldn't change
assert(errno == fakePureErrno()); // errno shouldn't change
assert(x !is null); // allocation should succeed

fakePureFree(x);

void* y = pureCalloc(10, 1); // normal zeroed allocation
assert(errno == fakePureGetErrno()); // errno shouldn't change
assert(errno == fakePureErrno()); // errno shouldn't change
assert(y !is null); // allocation should succeed

fakePureFree(y);

// subtract 2 because snn.lib adds 2 unconditionally before passing
// the size to the Windows API
void* z = pureMalloc(size_t.max - 2); // won't affect `errno`
assert(errno == fakePureGetErrno()); // errno shouldn't change
assert(errno == fakePureErrno()); // errno shouldn't change
assert(z is null);
}

// locally purified for internal use here only

extern (C) private @system @nogc nothrow
{
ref int fakePureErrnoImpl()
{
import core.stdc.errno;
return errno();
}
}

extern (C) private pure @system @nogc nothrow
{
pragma(mangle, "getErrno") int fakePureGetErrno();
pragma(mangle, "setErrno") int fakePureSetErrno(int);
pragma(mangle, "fakePureErrnoImpl") ref int fakePureErrno();

pragma(mangle, "malloc") void* fakePureMalloc(size_t);
pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size);
Expand Down
77 changes: 70 additions & 7 deletions src/core/stdc/errno.d
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Sean Kelly, Alex Rønne Petersen
* Source: $(DRUNTIMESRC core/stdc/_errno.d)
* Source: https://github.com/dlang/druntime/blob/master/src/core/stdc/errno.d
* Standards: ISO/IEC 9899:1999 (E)
*/

Expand All @@ -27,15 +27,78 @@ else version (WatchOS)
nothrow:
@nogc:

///
@property int errno() { return getErrno(); }
///
@property int errno(int n) { return setErrno(n); }
version (CRuntime_DigitalMars)
{
extern (C)
{
ref int _errno();
alias errno = _errno;
}
}
else version (CRuntime_Microsoft)
{
extern (C)
{
ref int _errno();
alias errno = _errno;
}
}
else version (CRuntime_Glibc)
{
extern (C)
{
ref int __errno_location();
alias errno = __errno_location;
}
}
else version (FreeBSD)
{
extern (C)
{
ref int __error();
alias errno = __error;
}
}
else version (linux)
{
extern (C)
{
ref int __errno_location();
alias errno = __errno_location;
}
}
else version (Darwin)
{
extern (C)
{
ref int __error();
alias errno = __error;
}
}
else version (OSX)
{
extern (C)
{
ref int __error();
alias errno = __error;
}
}
else
{
///
@property int errno() { return getErrno(); }
///
@property int errno(int n) { return setErrno(n); }

extern (C)
{
private int getErrno(); // for internal use
private int setErrno(int); // for internal use
}
}

extern (C):

private extern (C) int getErrno(); // for internal use
private extern (C) int setErrno(int); // for internal use

version( Windows )
{
Expand Down