Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Smith committed Feb 12, 2011
0 parents commit 7380bc0
Show file tree
Hide file tree
Showing 12 changed files with 339 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ebin/*
priv/*
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
all: compile test

compile:
@./rebar compile

clean:
@./rebar clean

test:
@./rebar eunit

eunit:
@./rebar eunit
48 changes: 48 additions & 0 deletions c_src/erl_nif_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef ERL_NIF_COMPAT_H_
#define ERL_NIF_COMPAT_H_

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include "erl_nif.h"

#if ERL_NIF_MAJOR_VERSION == 1 && ERL_NIF_MINOR_VERSION == 0

#define enif_open_resource_type_compat enif_open_resource_type
#define enif_alloc_resource_compat enif_alloc_resource
#define enif_release_resource_compat enif_release_resource
#define enif_alloc_binary_compat enif_alloc_binary
#define enif_alloc_compat enif_alloc
#define enif_free_compat enif_free
#endif /* R13B04 */

#if ERL_NIF_MAJOR_VERSION == 2 && ERL_NIF_MINOR_VERSION == 0

#define enif_open_resource_type_compat(E, N, D, F, T) \
enif_open_resource_type(E, NULL, N, D, F, T)

#define enif_alloc_resource_compat(E, T, S) \
enif_alloc_resource(T, S)

#define enif_release_resource_compat(E, H) \
enif_release_resource(H)

#define enif_alloc_binary_compat(E, S, B) \
enif_alloc_binary(S, B)

#define enif_alloc_compat(E, S) \
enif_alloc(S)

#define enif_free_compat(E, P) \
enif_free(P)

#endif /* R14 */



#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* ERL_NIF_COMPAT_H_ */
86 changes: 86 additions & 0 deletions c_src/pteracuda_nifs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// -------------------------------------------------------------------
//
// pteracuda: An Erlang framework for performing CUDA-enabled operations
//
// Copyright (c) 2011 Hypothetical Labs, Inc. All Rights Reserved.
//
// This file is provided to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// -------------------------------------------------------------------
#include "erl_nif.h"
#include "pteracuda_worker.h"

extern "C" {
static ErlNifResourceType *pteracuda_worker_resource;
static ErlNifResourceType *pteracuda_buffer_resource;

static int pteracuda_on_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info);

ERL_NIF_TERM pteracuda_nifs_new_worker(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM pteracuda_nifs_destroy_worker(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);

static ErlNifFunc pteracuda_nif_funcs[] = {
{"new_worker", 0, pteracuda_nifs_new_worker},
{"destroy_worker", 1, pteracuda_nifs_destroy_worker}
};
}

ERL_NIF_TERM ATOM_OK;
ERL_NIF_TERM ATOM_ERROR;
ERL_NIF_TERM OOM_ERROR;

ERL_NIF_INIT(pteracuda_nifs, pteracuda_nif_funcs, &pteracuda_on_load, NULL, NULL, NULL);

static int pteracuda_on_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) {
ATOM_OK = enif_make_atom(env, "ok");
ATOM_ERROR = enif_make_atom(env, "error");
pteracuda_worker_resource = enif_open_resource_type(env, NULL, "pteracuda_worker_resource",
NULL, ERL_NIF_RT_CREATE, 0);
pteracuda_buffer_resource = enif_open_resource_type(env, NULL, "pteracuda_buffer_resource",
NULL, ERL_NIF_RT_CREATE, 0);

/* Pre-alloate OOM error in case we run out of memory later */
OOM_ERROR = enif_make_tuple2(env, ATOM_ERROR, enif_make_atom(env, "out_of_memory"));
return 0;
}

ERL_NIF_TERM pteracuda_nifs_new_worker(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
ERL_NIF_TERM retval = ATOM_ERROR;
pcuda_worker *worker = (pcuda_worker *) enif_alloc_resource(pteracuda_worker_resource, sizeof(pcuda_worker));
/* Oops. Couldn't allocate worker */
if (worker == NULL) {
return OOM_ERROR;
}
if (pcuda_create_worker(worker)) {
ERL_NIF_TERM result = enif_make_resource(env, worker);
enif_release_resource(worker);
retval = enif_make_tuple2(env, ATOM_OK, result);
}
else {
pcuda_destroy_worker(worker);
enif_free(worker);
retval = ATOM_ERROR;
}
return retval;
}

ERL_NIF_TERM pteracuda_nifs_destroy_worker(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
pcuda_worker *worker;
if (argc != 1 || !enif_get_resource(env, argv[0], pteracuda_worker_resource, (void **) &worker)) {
return enif_make_badarg(env);
}
pcuda_destroy_worker(worker);
return ATOM_OK;
}
65 changes: 65 additions & 0 deletions c_src/pteracuda_worker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <stdio.h>
#include <unistd.h>
#include "pteracuda_worker.h"

int handle_command(pcuda_command *command) {
return 0;
}

void *pcuda_worker_loop(void *args) {
pcuda_worker *worker = (pcuda_worker *) args;
int keep_running = 1;
enif_mutex_lock(worker->command_guard);
while(keep_running) {
enif_cond_wait(worker->command_flag, worker->command_guard);
if (worker->queue->size() > 0) {
pcuda_command *cmd = worker->queue->front();
keep_running = handle_command(cmd);
free(cmd);
}
}
enif_mutex_unlock(worker->command_guard);
return NULL;
}

int pcuda_create_worker(pcuda_worker *worker) {
int retval = 0;
if ((worker->command_flag = enif_cond_create((char *) "pcuda_worker")) != NULL &&
(worker->command_guard = enif_mutex_create((char *) "pcuda_worker")) != NULL) {
worker->queue = new std::deque<pcuda_command *>();
if (enif_thread_create((char *) "pcuda_worker", &(worker->tid), pcuda_worker_loop, worker, NULL) == 0) {
/* UGLY UGLY Hack */
usleep(50 * 1000);
worker->running = 1;
retval = 1;
}
else {
retval = 0;
}
}
return retval;
}

void pcuda_destroy_worker(pcuda_worker *worker) {
if (worker->running) {
pcuda_command *cmd = (pcuda_command *) malloc(sizeof(pcuda_command));
pcuda_enqueue_command(worker, cmd);
enif_thread_join(worker->tid, NULL);
}
if (worker->command_guard != NULL) {
enif_mutex_destroy(worker->command_guard);
}
if (worker->command_flag != NULL) {
enif_cond_destroy(worker->command_flag);
}
if (worker->queue != NULL) {
delete worker->queue;
}
}

void pcuda_enqueue_command(pcuda_worker *worker, pcuda_command *cmd) {
enif_mutex_lock(worker->command_guard);
worker->queue->push_front(cmd);
enif_mutex_unlock(worker->command_guard);
enif_cond_signal(worker->command_flag);
}
26 changes: 26 additions & 0 deletions c_src/pteracuda_worker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef PCDUA_WORKER
#define PCUDA_WORKER

#include "erl_nif.h"
#include <deque>
#include <string>

typedef struct _pcuda_command {
int cmd;
void *args;
ErlNifPid caller;
} pcuda_command;

typedef struct _pcuda_worker {
int running;
ErlNifTid tid;
ErlNifMutex *command_guard;
ErlNifCond *command_flag;
std::deque<pcuda_command *> *queue;
} pcuda_worker;

int pcuda_create_worker(pcuda_worker *worker);
void pcuda_destroy_worker(pcuda_worker *worker);
void pcuda_enqueue_command(pcuda_worker *worker, pcuda_command *command);

#endif
Binary file added rebar
Binary file not shown.
4 changes: 4 additions & 0 deletions rebar.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{port_sources, ["c_src/*.cpp"]}.
{so_name, "pteracuda_nifs.so"}.

{port_envs, [{"(linux|solaris)", "LDFLAGS", "$LDFLAGS -lstdc++"}]}.
12 changes: 12 additions & 0 deletions src/pteracuda.app.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{application, pteracuda,
[
{description, ""},
{vsn, "1"},
{registered, []},
{applications, [
kernel,
stdlib
]},
{mod, { pteracuda_app, []}},
{env, []}
]}.
16 changes: 16 additions & 0 deletions src/pteracuda_app.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-module(pteracuda_app).

-behaviour(application).

%% Application callbacks
-export([start/2, stop/1]).

%% ===================================================================
%% Application callbacks
%% ===================================================================

start(_StartType, _StartArgs) ->
pteracuda_sup:start_link().

stop(_State) ->
ok.
39 changes: 39 additions & 0 deletions src/pteracuda_nifs.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
-module(pteracuda_nifs).

-define(NIF_API_VERSION, 1).
-define(MISSING_NIF, throw({error, missing_nif})).

-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.

-on_load(init/0).

-export([init/0]).

%% API
-export([new_worker/0,
destroy_worker/1]).

new_worker() ->
?MISSING_NIF.

destroy_worker(_Worker) ->
?MISSING_NIF.

init() ->
PrivDir = case code:priv_dir(pteracuda) of
{error, bad_name} ->
D = filename:dirname(code:which(?MODULE)),
filename:join([D, "..", "priv"]);
Dir ->
Dir
end,
SoName = filename:join([PrivDir, "pteracuda_nifs"]),
erlang:load_nif(SoName, ?NIF_API_VERSION).

-ifdef(TEST).
create_destroy_test() ->
{ok, W} = pteracuda_nifs:new_worker(),
pteracuda_nifs:destroy_worker(W).
-endif.
28 changes: 28 additions & 0 deletions src/pteracuda_sup.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

-module(pteracuda_sup).

-behaviour(supervisor).

%% API
-export([start_link/0]).

%% Supervisor callbacks
-export([init/1]).

%% Helper macro for declaring children of supervisor
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).

%% ===================================================================
%% API functions
%% ===================================================================

start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).

%% ===================================================================
%% Supervisor callbacks
%% ===================================================================

init([]) ->
{ok, { {one_for_one, 5, 10}, []} }.

0 comments on commit 7380bc0

Please sign in to comment.