libnrm API

The following describes the C API for libnrm instrumentation. The corresponding header file can be found in src/nrm.h. See the Examples for code samples and more information.

Library Initialization

int nrm_init(int *argc, char **argv[])

Main NRM header, contains most of the nrm public API initializes the library, in particular using environment variables to figure out if the library should emit messages at all and if a ratelimit is in place.

If the library detects command line options it understands, it will consume those arguments and modify the two variables accordingly. Other arguments will be ignored. It is safe to give a program’s main arguments to this library.

Parameters
  • argc[inout] a pointer to the number of arguments in *argv

  • argv[inout] an array of command line options.

Returns

0 if successful; an error code otherwise.

int nrm_finalize(void)

Terminates the library. Do this before an instrumented program exits.

Returns

0 if successful; an error code otherwise.

Client Configuration and Reports

NRM clients are used by any program that intends to communicate with a NRM daemon (nrmd). Initiate most RPCs, retrieve information about the state of the daemon, register new elements, send events, listen to state changes.

libnrm also features a command-line nrmc utility that mirrors most client functionality.

int nrm_client_create(nrm_client_t **client, const char *uri, int pub_port, int rpc_port)

Creates a new NRM Client.

Parameters
  • client – pointer to a variable that contains the created client handle

  • uri – address for connecting to nrmd

  • pub_port

  • rpc_port

Returns

0 if successful, an error code otherwise

int nrm_client_find(nrm_client_t *client, int type, const char *uuid, nrm_vector_t **results)

Find matching NRM objects within a client

Parameters
  • client – NRM client

  • type – An NRM scope, sensor, or slice type

  • uuid – name/uuid of the object to find

  • results – NRM vector for containing results

Returns

0 if successful, an error code otherwise

int nrm_client_send_event(nrm_client_t *client, nrm_time_t time, nrm_sensor_t *sensor, nrm_scope_t *scope, double value)

Sends a measurement to the NRM daemon

Parameters
  • client – NRM client object

  • time – a time value retrieved via nrm_time_gettime(&time)

  • sensor – NRM sensor object

  • scope – NRM scope object

  • value – a measurement to send to the NRM daemon`

Returns

0 if successful, an error code otherwise

int nrm_client_send_exit(nrm_client_t *client)

Asks the daemon to exit

Parameters

client – NRM client object

Returns

0 if successful, an error code otherwise

void nrm_client_destroy(nrm_client_t **client)

Removes an NRM client. Do this for each client before an instrumented program exits.

int nrm_client_add_scope(nrm_client_t *client, nrm_scope_t *scope)

Adds an NRM scope to an NRM client.

Returns

0 if successful, an error code otherwise

int nrm_client_list_scopes(nrm_client_t *client, nrm_vector_t **scopes)

Lists an NRM client’s registered scopes into a vector

Returns

0 if successful, an error code otherwise

int nrm_client_remove_scope(nrm_client_t *client, nrm_scope_t *scope)

Removes an NRM scope from a daemon

Returns

0 if successful, an error code otherwise

int nrm_client_add_sensor(nrm_client_t *client, nrm_sensor_t *sensor)

Adds an NRM sensor to an NRM client.

Returns

0 if successful, an error code otherwise

int nrm_client_list_sensors(nrm_client_t *client, nrm_vector_t **sensors)

Lists an NRM client’s registered sensors into a vector

Returns

0 if successful, an error code otherwise

int nrm_client_remove_sensor(nrm_client_t *client, nrm_sensor_t *sensor)

Removes an NRM sensor from a daemon

Returns

0 if successful, an error code otherwise

int nrm_client_add_actuator(nrm_client_t *client, nrm_actuator_t *actuator)
int nrm_client_list_actuators(nrm_client_t *client, nrm_vector_t **actuators)
int nrm_client_remove_actuator(nrm_client_t *client, nrm_actuator_t *actuator)

Removes an NRM actuator from a daemon

Returns

0 if successful, an error code otherwise

int nrm_client_actuate(nrm_client_t *client, nrm_actuator_t *actuator, double value)
int nrm_client_add_slice(nrm_client_t *client, nrm_slice_t *slice)

Adds an NRM slice to an NRM client.

Returns

0 if successful, an error code otherwise

int nrm_client_list_slices(nrm_client_t *client, nrm_vector_t **slices)

Lists an NRM client’s registered slices into a vector

Returns

0 if successful, an error code otherwise

int nrm_client_remove_slice(nrm_client_t *client, nrm_slice_t *slice)

Removes an NRM slice from a daemon

Returns

0 if successful, an error code otherwise

int nrm_client_set_event_listener(nrm_client_t *client, nrm_client_event_listener_fn fn)

Set a callback function for client events

Parameters
  • client – NRM client object

  • fn – function reference

Returns

0 if successful, an error code otherwise

int nrm_client_start_event_listener(const nrm_client_t *client, nrm_string_t topic)

Start a callback function for client events

Parameters
  • client – NRM client object

  • topic – NRM string label

Returns

0 if successful, an error code otherwise

int nrm_client_set_actuate_listener(nrm_client_t *client, nrm_client_actuate_listener_fn fn)
int nrm_client_start_actuate_listener(const nrm_client_t *client)

Scope Configuration

An NRM scope contains a list of resources corresponding to a type of progress to be reported to NRM. Types of progress reports include:

NRM_SCOPE_TYPE_CPU
NRM_SCOPE_TYPE_NUMA
NRM_SCOPE_TYPE_GPU

Functions

nrm_scope_t *nrm_scope_create(const char *name)

Creates and returns a new NRM scope

int nrm_scope_add(nrm_scope_t *scope, unsigned int type, unsigned int num)

Add an int corresponding to some hardware ID to the list

Parameters
  • scope – scope pointer

  • type – an int for some NRM_SCOPE_TYPE_

  • num – an integer corresponding to some hardware ID

int nrm_scope_add_atomic(nrm_scope_t *scope, unsigned int type, unsigned int num)

Note

For example, if reporting power usage for one socket and one GPU, you may want to instantiate two scopes. For the first scope, while looping over corresponding CPU logical indexes, call nrm_scope_add() with NRM_SCOPE_TYPE_CPU and set num to each index.

size_t nrm_scope_length(const nrm_scope_t *scope, unsigned int type)

Size of the list (number of elements)

Parameters
  • scope – scope pointer

  • type – an int for some NRM_SCOPE_TYPE_

int nrm_scope_destroy(nrm_scope_t *scope)

Removes an NRM scope. Do this for each scope before an instrumented program exits.

Returns

0 if successful, an error code otherwise

nrm_scope_t *nrm_scope_dup(nrm_scope_t *scope)

Creates and returns a pointer to a copy of an NRM scope

int nrm_scope_cmp(nrm_scope_t *one, nrm_scope_t *two)

Compares two NRM scopes.

Returns

0 if equivalent, 1 otherwise

int nrm_scope_snprintf(char *buf, size_t bufsize, const nrm_scope_t *scope)

snprintf the contents of an NRM scope

Returns

0 if successful, an error code otherwise

int nrm_scope_threadshared(nrm_scope_t *scope)
int nrm_scope_threadprivate(nrm_scope_t *scope)

Sensor Configuration

An NRM sensor corresponds to events to be reported to NRM.

nrm_sensor_t *nrm_sensor_create(const char *name)

Creates a new NRM sensor

Parameters

name – char pointer to a name describing the sensor

Returns

: a new NRM sensor structure

void nrm_sensor_destroy(nrm_sensor_t**)

Removes an NRM sensor. Do this for each sensor before an instrumented program exits.

Slice Configuration

An NRM slice names and assigns a uuid to a set of resources.

nrm_slice_t *nrm_slice_create(const char *name)

Creates a new NRM slice

Parameters

name – char pointer to a name describing the slice

Returns

: a new NRM slice structure

void nrm_slice_destroy(nrm_slice_t**)

Removes an NRM slice. Do this for each slice before an instrumented program exits.

void nrm_slice_fprintf(FILE *out, nrm_slice_t*)

Prints an NRM slice’s contents to the specified output file.

Logging Interface

int nrm_log_init(FILE *f, const char *nm)

Initializes NRM logging

Parameters
  • f – file descriptor

  • nm – logging source namespace

Returns

0 if successful, an error code otherwise

int nrm_log_setlevel(int level)

Log Levels include:

NRM_LOG_QUIET
NRM_LOG_ERROR
NRM_LOG_WARNING
NRM_LOG_NORMAL
NRM_LOG_INFO
NRM_LOG_DEBUG

Functions

void nrm_log_printf(int level, const char *file, unsigned int line, const char *format, ...)

Prints an NRM log message at a log level, labeled with source file and line number.

Parameters
  • level – log level constant

  • file – source file label typically __FILE__

  • line – source line number label. typically __LINE__

  • format – printf formatted string

Note

Optionally use nrm_log_error(), nrm_log_warning(), nrm_log_normal(), nrm_log_info(), or nrm_log_debug() in place of nrm_log_printf() for sensible defaults:

Timers

High Resolution Timers type and functions to save a timestamp and compute a difference. Resolution should be in nanoseconds.

typedef struct timespec nrm_time_t

Define type used to internally save timestamps (in nanoseconds since epoch)

void nrm_time_gettime(nrm_time_t *now)

Save timestamps into timer

int64_t nrm_time_diff(const nrm_time_t *start, const nrm_time_t *end)

Compute the time difference between two timestamps, as nanoseconds.

int64_t nrm_time_tons(const nrm_time_t *time)

Convert timestamp into nanoseconds since epoch, as an int64_t value

nrm_time_t nrm_time_fromns(int64_t time)

Convert a nanoseconds timestamp into an NRM time value