---
name: "pmhash"
section: "3"
platform: "linux"
package: "pcp"
version: "7.2.2-2"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/pmhash"
---

# pmhash(3)

general purpose hashing routines

## NAME

**\_\_pmHashInit**, **\_\_pmHashPreAlloc**, **\_\_pmHashAdd**, **\_\_pmHashDel**, **\_\_pmHashSearch**, **\_\_pmHashWalk**, **\_\_pmHashWalkCB**, **\_\_pmHashFree**, **\_\_pmHashClear** - general purpose hashing routines

## C SYNOPSIS

**#include \<pcp/pmapi.h\>**\
 **#include \<pcp/libpcp.h\>**

**void \_\_pmHashInit(\_\_pmHashCtl \****hcp***);**\
 **int \_\_pmHashPreAlloc(int** *hsize***, \_\_pmHashCtl \****hcp***);**\
 **int \_\_pmHashAdd(unsigned int** *key***,** **void \****data***,** **\_\_pmHashCtl \****hcp***);**\
 **int \_\_pmHashDel(unsigned int** *key***,** **void \****data***,** **\_\_pmHashCtl \****hcp***);**\
 **\_\_pmHashNode \*\_\_pmHashSearch(unsigned int** *key***,** **\_\_pmHashCtl \****hcp***);**\
 **\_\_pmHashNode \*\_\_pmHashWalk(\_\_pmHashCtl \****hcp***,** **\_\_pmHashWalkState** *state***);**\
 **void \_\_pmHashWalkCB(\_\_pmHashWalkCallback** *cb***,** **void \****cdata***,** **const \_\_pmHashCtl \****hcp***);**\
 **void \_\_pmHashFree(\_\_pmHashCtl \****hcp***);**\
 **void \_\_pmHashClear(\_\_pmHashCtl \****hcp***);**

**cc ... -lpcp**

## CAVEAT

This documentation is intended for internal Performance Co-Pilot (PCP) developer use.

These interfaces are not part of the PCP APIs that are guaranteed to remain fixed across releases, and at some point in the future they may not work or may provide different semantics.

## DESCRIPTION

The **\_\_pmHash** group of routines implement a generalized suite of linear hashing services based on a *key* that is an unsigned int and *data* that is an opaque pointer to information the caller wishes to associate with *key*.

The data type of *key* makes is suitable for hashed access based on metric identifier (**pmID**), instance domain number (**pmInDom**) or internal instance identifiers within an instance domain.

Multiple hash tables may exist, each identified by a hash control struct (**\_\_pmHashCtl**) **hcp** which is declared by the caller and initialized by calling **\_\_pmHashInit**. Refer to the **HASH CONTROL** and **HASH NODE** sections below for more information on the hash table internal data structures.

The hash table is initially empty but dynamically grows by approximate doubling in size as entries are added, and this may cause some organizational overhead in relinking the hash chains when the hash table grows. This overhead can be avoided by optionally calling **\_\_pmHashPreAlloc** with an initial hash table size of *hsize* entries, but this must be done after calling **\_\_pmHashInit** and before any entries are added.

Entries are added to a hash table by calling **\_\_pmHashAdd**. The opaque *data* is typically a pointer to a block of additional information to be associated with the *key*, although it may be **NULL** if there is no additional information required or currently available.

Although usually not required, duplicate *key* values can be stored in a hash table and **\_\_pmHashAdd** will silently add these (presumably with a different *data* pointer). If uniqueness of *key*s is required, it is necessary to call **\_\_pmHashSearch** first to determine that there is no entry for *key*, before calling **\_\_pmHashAdd**.

Entries may be removed from a hash table using **\_\_pmHashDel** where the entry to be deleted is the *first* one with a matching *key* and *data* pointer. See the note above about duplicate keys to understand why the *data* parameter is needed.

**\_\_pmHashSearch** finds the *first* entry with a matching *key*. If duplicate keys are being stored, then the caller will have to follow the *hp*-\>*next* chain looking for additional entries with the same *key*. Refer to the **HASH CONTROL** and **HASH NODE** sections below for more information on the hash table internal data structures.

**\_\_pmHashWalk** provides a stateful interface to walk each node in the hash table. It is first called with *state* set to **PM\_HASH\_WALK\_START** to retrieve the first entry and then repeatedly called with *state* set to **PM\_HASH\_WALK\_NEXT** to retrieve subsequent entries.

**\_\_pmHashWalkCB** provides an alternative method to traverse the hash table. The callback function *cb* is called with two arguments, a pointer to the current hash entry and *cdata* (the latter allows the caller to pass auxiliary information into the callback function, but can be **NULL** if this is not required). The callback function must return one of the following **\_\_pmHashWalkState** values:

- **PM\_HASH\_WALK\_NEXT**

  continue the traversal

- **PM\_HASH\_WALK\_STOP**

  terminate the traversal

- **PM\_HASH\_DELETE\_NEXT**

  delete the current node from the hash table and continue the traversal

- **PM\_HASH\_DELETE\_STOP**

  delete the current node from the hash table and terminate the traversal

**\_\_pmHashFree** will release all storage associated with the hash table and return the hash table to the empty state, just like after **\_\_pmHashInit** has been called. But **\_\_pmHashFree** cannot free any storage attached via the *data* argument to **\_\_pmHashAdd** calls. So the most appropriate way to clean up the hash table is to first traverse the table releasing any *data* and then call **\_\_pmHashFree** as the example below shows.

```
__pmHashCtl	hash;
__pmHashWalkState
mycallback(const __pmHashNode *hp, void *cp)
{
    (void)cp;
    if (hp->data) {
	/*
	 * free() if malloc'd or some datum-specific
	 * method, e.g. __pmFreeProfile()
	 */
        free(hp->data);
    }
    return PM_HASH_WALK_NEXT;
}
...
    __pmHashWalkCB(mycallback, NULL, &hash);
    __pmHashFree(&hash);
}
```

**\_\_pmHashClear** returns the hash table to the empty state, just like after **\_\_pmHashInit** has been called. Beware that **\_\_pmHashClear** does not release any storage associated with hash entries, and so risks leaking memory, however the following example shows how to release all memory in a single traversal of the hash table with **\_\_pmHashWalkCB** before calling **\_\_pmHashClear**.

```
__pmHashCtl	hash;
__pmHashWalkState
mycallback(const __pmHashNode *hp, void *cp)
{
    (void)cp;
    if (hp->data) {
	/*
	 * free() if malloc'd or some datum-specific
	 * method, e.g. __pmFreeProfile()
	 */
        free(hp->data);
    }
    /*
     * compared to the previous example, this difference
     * is important and frees each hash node
     */
    return PM_HASH_DELETE_NEXT;
}
...
    __pmHashWalkCB(mycallback, NULL, &hash);
    __pmHashClear(&hash);
}
```

## HASH CONTROL

The **\_\_pmHashCtl** struct is defined as:

```
typedef struct __pmHashCtl {
    int                 nodes;
    int                 hsize;
    __pmHashNode        **hash;
    __pmHashNode        *next;
    unsigned int        index;
} __pmHashCtl;
```

The hash table *hash* contains *hsize* entries, each of which may point to a linked list of hash nodes. The total number of hash nodes is held in *nodes*. The *index* and *next* fields are used to maintain state during hash table walk operations.

## HASH NODE

The **\_\_pmHashNode** struct is defined as:

```
typedef struct __pmHashNode {
    struct __pmHashNode *next;
    unsigned int        key;
    void                *data;
} __pmHashNode;
```

Each node holds the *key*, the opaque pointer (*data*) and *next* implements the linked list of hash nodes from each entry in the hash table.

## DIAGNOSTICS AND RETURN VALUES

**\_\_pmHashPreAlloc** returns -1 if the hash table is not empty, else a value \< 0 to indicate an error, probably from [**calloc**(3)](/calloc/3.md), that can be turned into an error message by calling [**pmErrStr**(3)](/pmErrStr/3.md).

**\_\_pmHashAdd** returns 1 for success, else a value \< 0 to indicate an error, probably from [**calloc**(3)](/calloc/3.md).

Return values from **\_\_pmHashDel** are 0 if no matching entry is found, else 1 if a matching entry was deleted.

**\_\_pmHashSearch** returns with a pointer to the entry if found, else **NULL**.

**\_\_pmHashWalk** returns with a pointer to the next entry if found, else **NULL** when all entries have been traversed.

## SEE ALSO

[**PMAPI**(3)](/PMAPI/3.md), [**calloc**(3)](/calloc/3.md), [**free**(3)](/free/3.md) and [**pmErrStr**(3)](/pmErrStr/3.md).
