casting question in kernel source code

R

rahul8143

hello,
In kernel source code there is ip_fragment.c file my question is
regarding pointer function and casting for that look at required
snippet from that file
There is structure defined for queueing ip fragments as
struct ipq {
struct ipq *next; /* linked list pointers */
struct list_head lru_list; /* lru list member */
u32 user;
u32 saddr;
u32 daddr;
u16 id;
u8 protocol;
u8 last_in;
#define COMPLETE 4
#define FIRST_IN 2
#define LAST_IN 1

struct sk_buff *fragments; /* linked list of received fragments */
int len; /* total length of original datagram */
int meat;
spinlock_t lock;
atomic_t refcnt;
struct timer_list timer; /* when will this queue expire? */
struct ipq **pprev;
int iif;
struct timeval stamp;
};


static void ip_expire(unsigned long arg)
{
struct ipq *qp = (struct ipq *) arg;

spin_lock(&qp->lock);

if (qp->last_in & COMPLETE)
goto out;

ipq_kill(qp);
.....
.....
....
}

static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32
user)
{
struct ipq *qp;

if ((qp = frag_alloc_queue()) == NULL)
goto out_nomem;

qp->protocol = iph->protocol;
qp->last_in = 0;
qp->id = iph->id;
qp->saddr = iph->saddr;
qp->daddr = iph->daddr;
qp->user = user;
qp->len = 0;
qp->meat = 0;
qp->fragments = NULL;
qp->iif = 0;

/* Initialize a timer for this entry. */
init_timer(&qp->timer);
qp->timer.data = (unsigned long) qp; /* pointer to queue */
qp->timer.function = ip_expire; /* expire function */
qp->lock = SPIN_LOCK_UNLOCKED;
atomic_set(&qp->refcnt, 1);

return ip_frag_intern(hash, qp);
}


My question is
1)how ip_expire is called in ip_frag_create? I mean where is its
argument. check that function above.
2) how following casting occurs in ip_expire(unsigned long arg)
struct ipq *qp = (struct ipq *) arg;
how a unsigned long be converted to structure?
regards,
rahul.
 
E

Eric Sosman

hello,
In kernel source code there is ip_fragment.c file my question is
regarding pointer function and casting for that look at required
snippet from that file
[... snipped even further; see up-thread ...]

static void ip_expire(unsigned long arg)
{
struct ipq *qp = (struct ipq *) arg;

[... in function ip_frag_create() ...]
/* Initialize a timer for this entry. */
init_timer(&qp->timer);
qp->timer.data = (unsigned long) qp; /* pointer to queue */
qp->timer.function = ip_expire; /* expire function */
[...]

My question is
1)how ip_expire is called in ip_frag_create? I mean where is its
argument. check that function above.

This is not a function call at all. It is an assignment:
`X = Y'. The `X' is a field in a struct or union (we can
deduce that much from the `.' syntax), probably a struct.
You didn't show the declaration of this struct or union type,
but we can also infer that its `function' field is a pointer.
Not a pointer to a data object, but a pointer to a function --
and the `Y' piece is the "target" of this pointer, the function
that the pointer points to.

At some later time, some piece of code probably makes a
call that looks something like

qp->timer.function(qp->timer.data);

.... and this will invoke the ip_expire() function.
2) how following casting occurs in ip_expire(unsigned long arg)
struct ipq *qp = (struct ipq *) arg;
how a unsigned long be converted to structure?

First, the `unsigned long' is not being converted to a
struct. It's being converted to a struct pointer, which is
a very different thing.

Second, the conversion is unsafe. Converting an integer
type to a pointer gives an implementation-defined result that
might not be useful at all. Some sloppy code (like the above)
assumes that these conversions will simply "preserve all the
bits" (if the integer has at least as many bits as a pointer),
but the C language does not guarantee this. The code relies
on the quirks of a particular compiler in a particular environment,
and is suspect in all other environments.

Note the corresponding conversion in the assignment to
`qp->timer.data' (which probably winds up being passed to
ip_expire() as its argument). This takes the pointer `qp' and
converts it to an `unsigned long' -- and again, the result is
implementation-defined and might not be useful.

Code like this has a nasty habit of working just fine for
a long time on many machines, and then comes the day when it's
ported to a machine of a different kind and things suddenly
go wrong. We went through this when implementations started
using 32 bits for `int' instead of 16, and we went through it
again when 64-bit quantities came along -- and it looks like
this chunk of code never learned those hard lessons.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,967
Messages
2,570,148
Members
46,694
Latest member
LetaCadwal

Latest Threads

Top