Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between LIST_HEAD_INIT and INIT_LIST_HEAD

I'm trying to understand the Linux kernel linked list API.

According to Linux Kernel Linked List I should initialize the list head by INIT_LIST_HEAD but here (Linux Kernel Program) it's suggested to use LIST_HEAD_INIT instead.

Here's a working code I wrote, but I'm not sure if I did it in proper way. Could someone verify that it's OK?

#include <stdio.h>
#include <stdlib.h>
#include "list.h"

typedef struct edge_attr {
        int d;
        struct list_head list;
} edge_attributes_t;

typedef struct edge {
        int id;
        edge_attributes_t *attributes;
} edge_t;

int main () {
        int i;
        struct list_head *pos;
        edge_attributes_t *elem;
        edge_t *a = (edge_t*)malloc(sizeof(edge_t));

        a->id = 12;
        a->attributes = (edge_attributes_t*) malloc(sizeof(edge_attributes_t));

        INIT_LIST_HEAD(&a->attributes->list);

        for (i=0; i<5; ++i) {
                elem = (edge_attributes_t*)malloc(sizeof(edge_attributes_t));
                elem->d = i;
                list_add(&elem->list, &a->attributes->list);
        }

        list_for_each(pos, &(a->attributes->list)) {
                elem = list_entry(pos, edge_attributes_t, list);
                printf("%d \n", elem->d);
        }

        return 0;
}
like image 678
patseb Avatar asked Apr 21 '12 19:04

patseb


Video Answer


2 Answers

LIST_HEAD_INIT is a static initializer, INIT_LIST_HEAD is a function. They both initialise a list_head to be empty.

If you are statically declaring a list_head, you should use LIST_HEAD_INIT, eg:

static struct list_head mylist = LIST_HEAD_INIT(mylist);

You should use INIT_LIST_HEAD() for a list head that is dynamically allocated, usually part of another structure. There are many examples in the kernel source.

like image 109
mpe Avatar answered Oct 12 '22 23:10

mpe


A quick LXR search shows:

#define LIST_HEAD_INIT(name) { &(name), &(name) }

static inline void INIT_LIST_HEAD(struct list_head *list)
{
        list->next = list;
        list->prev = list;
}

So INIT_LIST_HEAD gets a struct list_head * and initializes it, while LIST_HEAD_INIT returns the address of the passed pointer in a suitable fashioned for use as an initializer for a list:

struct list_head lst1;
/* .... */
INIT_LIST_HEAD(&lst1);



struct list_head lst2 = LIST_HEAD_INIT(lst2);
like image 30
cnicutar Avatar answered Oct 12 '22 23:10

cnicutar