casting question in kernel source code

Discussion in 'C Programming' started by rahul8143@gmail.com, Apr 17, 2005.

  1. Guest

    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.
     
    , Apr 17, 2005
    #1
    1. Advertising

  2. Eric Sosman Guest

    wrote:
    > 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.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Apr 17, 2005
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. kevin
    Replies:
    11
    Views:
    5,808
    Andrew McDonagh
    Jan 8, 2005
  2. yogesh
    Replies:
    3
    Views:
    588
    Kenny McCormack
    Feb 12, 2006
  3. Eric Promislow
    Replies:
    0
    Views:
    88
    Eric Promislow
    Aug 9, 2005
  4. Replies:
    3
    Views:
    176
  5. Lars Gierth
    Replies:
    6
    Views:
    225
    David Masover
    Mar 20, 2010
Loading...

Share This Page