1#include <node.h>
2#include <v8.h>
3#include <stdlib.h>
4
5#ifdef _AIX
6// AIX allows over-allocation, and will SIGKILL when the allocated pages are
7// used if there is not enough VM. Check for available space until
8// out-of-memory.  Don't allow more then some (large) proportion of it to be
9// used for the test strings, so Node & V8 have some space for allocations.
10#include <signal.h>
11#include <sys/vminfo.h>
12
13static void* Allowed(size_t size) {
14  blkcnt_t allowedBlocks = psdanger(SIGKILL);
15
16  if (allowedBlocks < 1) {
17    // Already OOM
18    return nullptr;
19  }
20  const size_t BYTES_PER_BLOCK = 512;
21  size_t allowed = (allowedBlocks * BYTES_PER_BLOCK * 4) / 5;
22  if (size < allowed) {
23    return malloc(size);
24  }
25  return nullptr;
26}
27#else
28// Other systems also allow over-allocation, but this malloc-and-free approach
29// seems to be working for them.
30static void* Allowed(size_t size) {
31  return malloc(size);
32}
33#endif  // _AIX
34
35void EnsureAllocation(const v8::FunctionCallbackInfo<v8::Value> &args) {
36  v8::Isolate* isolate = args.GetIsolate();
37  uintptr_t size = args[0].As<v8::Integer>()->Value();
38  v8::Local<v8::Boolean> success;
39
40  void* buffer = Allowed(size);
41  if (buffer) {
42    success = v8::Boolean::New(isolate, true);
43    free(buffer);
44  } else {
45    success = v8::Boolean::New(isolate, false);
46  }
47  args.GetReturnValue().Set(success);
48}
49
50void init(v8::Local<v8::Object> exports) {
51  NODE_SET_METHOD(exports, "ensureAllocation", EnsureAllocation);
52}
53
54NODE_MODULE(NODE_GYP_MODULE_NAME, init)
55