468,514 Members | 1,611 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,514 developers. It's quick & easy.

a confusing way to get a pointer's address

Hi,
i feel confused about the following program, and it's works to get a
pointer-member's address.

#define NETDEV_ALIGN 32
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)

static inline void *netdev_priv(struct net_device *dev)
{ return (char *)dev + ((sizeof(struct net_device)+
NETDEV_ALIGN_CONST)
& ~NETDEV_ALIGN_CONST);
}

Jul 2 '07 #1
11 3045
On 7 2 , 6 56 , !truth <noddy_zh...@asustek.com.cnwrote:
Hi,
i feel confused about the following program, and it's works to get a
pointer-member's address.

#define NETDEV_ALIGN 32
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)

static inline void *netdev_priv(struct net_device *dev)
{ return (char *)dev + ((sizeof(struct net_device)+
NETDEV_ALIGN_CONST)
& ~NETDEV_ALIGN_CONST);
}
sorry, i entry a wrong key, but did not finished my thread.

go on

the *struct net_device* is as follows, also you can refer to the
webpage:http://www.gelato.unsw.edu.au/lxr/source/include/linux/
netdevice.h#L260

260 struct net_device
261 {
262
263 /*
264 * This is the first field of the "visible" part of this
structure
265 * (i.e. as seen by users in the "Space.c" file). It is
the name
266 * the interface.
267 */
268 char name[IFNAMSIZ];
269 /* device name hash chain */
270 struct hlist_node name_hlist;
271
272 /*
273 * I/O specific fields
274 * FIXME: Merge these and struct ifmap into one
275 */
276 unsigned long mem_end; /* shared mem
end */
277 unsigned long mem_start; /* shared mem
start */
278 unsigned long base_addr; /* device I/O
address */
279 unsigned int irq; /* device IRQ
number */
280
281 /*
282 * Some hardware also needs these fields, but they
are not
283 * part of the usual set specified in Space.c.
284 */
285
286 unsigned char if_port; /* Selectable AUI,
TP,..*/
287 unsigned char dma; /* DMA
channel */
288
289 unsigned long state;
290
291 struct net_device *next;
292
293 /* The device initialization function. Called only once.
*/
294 int (*init)(struct net_device *dev);
295
296 /* ------- Fields preinitialized in Space.c finish here
------- */
297
298 /* Net device features */
299 unsigned long features;
300 #define NETIF_F_SG 1 /* Scatter/gather IO. */
301 #define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/
UDP over IPv4. */
302 #define NETIF_F_NO_CSUM 4 /* Does not require
checksum. F.e. loopack. */
303 #define NETIF_F_HW_CSUM 8 /* Can checksum all the
packets. */
304 #define NETIF_F_HIGHDMA 32 /* Can DMA to high memory.
*/
305 #define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */
306 #define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw
acceleration */
307 #define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw
acceleration */
308 #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on
VLAN */
309 #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle
VLAN packets */
310 #define NETIF_F_TSO 2048 /* Can offload TCP/IP
segmentation */
311 #define NETIF_F_LLTX 4096 /* LockLess TX */
312 #define NETIF_F_UFO 8192 /* Can offload UDP Large
Send*/
313
314 struct net_device *next_sched;
315
316 /* Interface index. Unique device identifier */
317 int ifindex;
318 int iflink;
319
320
321 struct net_device_stats* (*get_stats)(struct net_device
*dev);
322 struct iw_statistics* (*get_wireless_stats)(struct
net_device *dev);
323
324 /* List of functions to handle Wireless Extensions
(instead of ioctl).
325 * See <net/iw_handler.hfor details. Jean II */
326 const struct iw_handler_def * wireless_handlers;
327 /* Instance data managed by the core of Wireless
Extensions. */
328 struct iw_public_data * wireless_data;
329
330 struct ethtool_ops *ethtool_ops;
331
332 /*
333 * This marks the end of the "visible" part of the
structure. All
334 * fields hereafter are internal to the system, and may
change at
335 * will (read: may be cleaned up at will).
336 */
337
338
339 unsigned int flags; /* interface flags (a la
BSD) */
340 unsigned short gflags;
341 unsigned short priv_flags; /* Like 'flags' but
invisible to userspace. */
342 unsigned short padded; /* How much padding added
by alloc_netdev() */
343
344 unsigned char operstate; /* RFC2863 operstate */
345 unsigned char link_mode; /* mapping policy to
operstate */
346
347 unsigned mtu; /* interface MTU
value */
348 unsigned short type; /* interface hardware
type */
349 unsigned short hard_header_len; /*
hardware hdr length */
350
351 struct net_device *master; /* Pointer to master
device of a group,
352 * which this device is
member of.
353 */
354
355 /* Interface address info. */
356 unsigned char perm_addr[MAX_ADDR_LEN]; /*
permanent hw address */
357 unsigned char addr_len; /* hardware
address length */
358 unsigned short dev_id; /* for shared
network cards */
359
360 struct dev_mc_list *mc_list; /* Multicast mac
addresses */
361 int mc_count; /* Number of
installed mcasts */
362 int promiscuity;
363 int allmulti;
364
365
366 /* Protocol specific pointers */
367
368 void *atalk_ptr; /* AppleTalk
link */
369 void *ip_ptr; /* IPv4 specific
data */
370 void *dn_ptr; /* DECnet specific
data */
371 void *ip6_ptr; /* IPv6 specific
data */
372 void *ec_ptr; /* Econet specific
data */
373 void *ax25_ptr; /* AX.25 specific
data */
374
375 /*
376 * Cache line mostly used on receive path (including
eth_type_trans())
377 */
378 struct list_head poll_list
____cacheline_aligned_in_smp;
379 /* Link to poll list */
380
381 int (*poll) (struct net_device *dev,
int *quota);
382 int quota;
383 int weight;
384 unsigned long last_rx; /* Time of last
Rx */
385 /* Interface address info used in eth_type_trans() */
386 unsigned char dev_addr[MAX_ADDR_LEN]; /* hw
address, (before bcast
387 because
most packets are unicast) */
388
389 unsigned char broadcast[MAX_ADDR_LEN]; /*
hw bcast add */
390
391 /*
392 * Cache line mostly used on queue transmit path (qdisc)
393 */
394 /* device queue lock */
395 spinlock_t queue_lock
____cacheline_aligned_in_smp;
396 struct Qdisc *qdisc;
397 struct Qdisc *qdisc_sleeping;
398 struct list_head qdisc_list;
399 unsigned long tx_queue_len; /* Max frames per
queue allowed */
400
401 /* ingress path synchronizer */
402 spinlock_t ingress_lock;
403 struct Qdisc *qdisc_ingress;
404
405 /*
406 * One part is mostly used on xmit path (device)
407 */
408 /* hard_start_xmit synchronizer */
409 spinlock_t xmit_lock
____cacheline_aligned_in_smp;
410 /* cpu id of processor entered to hard_start_xmit or -1,
411 if nobody entered there.
412 */
413 int xmit_lock_owner;
414 void *priv; /* pointer to private
data */
415 int (*hard_start_xmit) (struct sk_buff
*skb,
416 struct
net_device *dev);
417 /* These may be needed for future network-power-down code.
*/
418 unsigned long trans_start; /* Time (in
jiffies) of last Tx */
419
420 int watchdog_timeo; /* used by
dev_watchdog() */
421 struct timer_list watchdog_timer;
422
423 /*
424 * refcnt is a very hot point, so align it on SMP
425 */
426 /* Number of references to this device */
427 atomic_t refcnt
____cacheline_aligned_in_smp;
428
429 /* delayed register/unregister */
430 struct list_head todo_list;
431 /* device index hash chain */
432 struct hlist_node index_hlist;
433
434 /* register/unregister state machine */
435 enum { NETREG_UNINITIALIZED=0,
436 NETREG_REGISTERED, /* completed
register_netdevice */
437 NETREG_UNREGISTERING, /* called
unregister_netdevice */
438 NETREG_UNREGISTERED, /* completed unregister
todo */
439 NETREG_RELEASED, /* called free_netdev */
440 } reg_state;
441
442 /* Called after device is detached from network. */
443 void (*uninit)(struct net_device *dev);
444 /* Called after last user reference disappears. */
445 void (*destructor)(struct net_device
*dev);
446
447 /* Pointers to interface service routines. */
448 int (*open)(struct net_device *dev);
449 int (*stop)(struct net_device *dev);
450 #define HAVE_NETDEV_POLL
451 int (*hard_header) (struct sk_buff
*skb,
452 struct net_device
*dev,
453 unsigned short
type,
454 void *daddr,
455 void *saddr,
456 unsigned len);
457 int (*rebuild_header)(struct sk_buff
*skb);
458 #define HAVE_MULTICAST
459 void (*set_multicast_list)(struct
net_device *dev);
460 #define HAVE_SET_MAC_ADDR
461 int (*set_mac_address)(struct
net_device *dev,
462 void *addr);
463 #define HAVE_PRIVATE_IOCTL
464 int (*do_ioctl)(struct net_device
*dev,
465 struct ifreq *ifr, int
cmd);
466 #define HAVE_SET_CONFIG
467 int (*set_config)(struct net_device
*dev,
468 struct ifmap *map);
469 #define HAVE_HEADER_CACHE
470 int (*hard_header_cache)(struct
neighbour *neigh,
471 struct
hh_cache *hh);
472 void (*header_cache_update)(struct
hh_cache *hh,
473 struct
net_device *dev,
474 unsigned
char * haddr);
475 #define HAVE_CHANGE_MTU
476 int (*change_mtu)(struct net_device
*dev, int new_mtu);
477
478 #define HAVE_TX_TIMEOUT
479 void (*tx_timeout) (struct net_device
*dev);
480
481 void (*vlan_rx_register)(struct
net_device *dev,
482 struct
vlan_group *grp);
483 void (*vlan_rx_add_vid)(struct
net_device *dev,
484 unsigned short
vid);
485 void (*vlan_rx_kill_vid)(struct
net_device *dev,
486 unsigned short
vid);
487
488 int (*hard_header_parse)(struct
sk_buff *skb,
489 unsigned char
*haddr);
490 int (*neigh_setup)(struct net_device
*dev, struct neigh_parms *);
491 #ifdef CONFIG_NETPOLL
492 struct netpoll_info *npinfo;
493 #endif
494 #ifdef CONFIG_NET_POLL_CONTROLLER
495 void (*poll_controller)(struct
net_device *dev);
496 #endif
497
498 /* bridge stuff */
499 struct net_bridge_port *br_port;
500
501 #ifdef CONFIG_NET_DIVERT
502 /* this will get initialized at each interface type init
routine */
503 struct divert_blk *divert;
504 #endif /* CONFIG_NET_DIVERT */
505
506 /* class/net/name entry */
507 struct class_device class_dev;
508 /* space for optional statistics and wireless sysfs groups
*/
509 struct attribute_group *sysfs_groups[3];
510 };

Jul 2 '07 #2
continue

my question is

1. the function is to get the address of *priv* in the structure
net_device at line 341, but how it can do that?

2.what's the *NETDEV_ALIGN_CONST* used for?

3.why not to do as follows:

struct net_device *dev;
void *tp;
/*alloc memory*/
tp=dev->priv

instead of
void *tp=netdev_priv(dev)
thanks.

Jul 2 '07 #3
On 2 Jul, 12:06, !truth <noddy_zh...@asustek.com.cnwrote:
continue

my question is

1. the function is to get the address of *priv* in the structure
net_device at line 341,...
No it isn't... It relates to the "priv" field at line 414, I think.

2.what's the *NETDEV_ALIGN_CONST* used for?
It's a technique to force specific alignment of data.
3.why not to do as follows:

struct net_device *dev;
void *tp;
/*alloc memory*/

tp=dev->priv

instead of
void *tp=netdev_priv(dev)
I don't _know_ - but presumably the developers of this code had a good
reason. My guess from a quick scan is that the design of the code
"knows" that the "private" data for a netdev structure is always put
in memory immediately after the netdev structure, aligned to a 32-byte
boundary. It's therefore quicker (and this is probably heavily used)
to get its address by pointer arithmetic than by a memory access...

I think you are asking about Linux kernel design issues rather than
pure C here. A quick Google for "netdev_priv" shows that this has been
discussed in publicly visible mailing lists.

If you are examining Linux sources, you may find
comp.os.linux.development.system and/or one of the mailing lists more
useful than a general C newsgroup.

Jul 2 '07 #4
On Mon, 02 Jul 2007 04:01:24 -0700, !truth
<no*********@asustek.com.cnwrote:
>On 7 2 , 6 56 , !truth <noddy_zh...@asustek.com.cnwrote:
>Hi,
i feel confused about the following program, and it's works to get a
pointer-member's address.

#define NETDEV_ALIGN 32
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)

static inline void *netdev_priv(struct net_device *dev)
{ return (char *)dev + ((sizeof(struct net_device)+
NETDEV_ALIGN_CONST)
& ~NETDEV_ALIGN_CONST);
}

sorry, i entry a wrong key, but did not finished my thread.

go on

the *struct net_device* is as follows, also you can refer to the
webpage:http://www.gelato.unsw.edu.au/lxr/source/include/linux/
netdevice.h#L260

260 struct net_device
261 {
snip internal details of struct
>510 };
I appended your third message below.
>my question is

1. the function is to get the address of *priv* in the structure
net_device at line 341, but how it can do that?
priv is at 414. 341 is priv_flags. Neither matters.

That is definitely not the intent of the function.

If the function wanted the address of the member priv, it
would use code of the form return &(dev->priv).

If the function wanted the offset of priv from the start of
the struct, it would use the offsetof macro.
>
2.what's the *NETDEV_ALIGN_CONST* used for?
This macro is defined to be the decimal value 31, which in hexadecimal
is 0x1f and in binary 0001 1111. It is used to perform boundary
alignment.

Consider the second half of the return expression (everything
following the first +):

sizeof evaluates to the actual size in bytes of the struct.
Just for sake of example, lets assume this is 27.

To this we add 31, giving us 58 which 0x3a or 0011 1010.

To this we bit-wise and the value ~31 which is the
ones-complement of 0x1f. This value is 0xe0 or 1110 0000. The result
of the operation is 0010 0000 or 0x20 or decimal 32.

You can try some other values for sizeof to convince yourself
that this subexpression will always compute the first multiple of 32
that is at least as large as the size of the struct. [In integer
arithmetic (X+N-1)/N always produces the first multiple of N that is
>= X. In this particular case, the code takes advantage of the fact
that (in binary representation) division by a power of 2 (32 is
pow(2,5)) can be accomplished by a bit-wise and using the
ones-complement of the divisor-1.]

We add this computed value to the address of the struct and return the
sum. The net result is the function returns the address of the first
byte that is beyond the end of the struct AND a multiple of 32 bytes
away from the start of the struct.
>
3.why not to do as follows:

struct net_device *dev;
void *tp;
/*alloc memory*/
What memory do you think needs to be allocated?
>

tp=dev->priv
After adding the missing semicolon, this does not produce the address
of priv. It produces the value that happens to be in priv, the
address of what it points to. If priv is not initialized or assigned
a value, the statement results in undefined behavior.
>
instead of
void *tp=netdev_priv(dev)
Having seen this in other code, I infer

dev points to an allocated struct, not a defined one.

The amount of space requested is (much) larger than needed
just for the struct.

The designer intends to use this excess space to hold
additional data related to the struct. (Based solely on your comments,
I expect that priv will eventually point to this private data.)

The designer has made the assumption that there is no object
type that will be processed by this code that has an alignment
requirement more restrictive than 32 bytes. Since malloc returns an
address X suitably aligned for any object, if the assumption is true
then X+32n will also be suitably aligned.
Remove del for email
Jul 2 '07 #5
Thanks really,but i was still confused by question 1 and 3.

I modify my question 1:

1. the function(netdev_priv) is to get the member of *priv* in the
structure
net_device at line 414, which means that *dev->priv* equals
*netdev_priv(dev)*, but how it can do that?

I write down an similar program as follows:

#include <stdio.h>
struct device{
int a;
void *priv;
int c;
char d;
};
#define NETDEV_ALIGN 32
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)
static inline void *netdev_priv(struct device *dev)
{ return (char *)dev + ((sizeof(struct device)+
NETDEV_ALIGN_CONST)
& ~NETDEV_ALIGN_CONST);
}
int main()
{
struct device devs;
struct device *dev;
dev=&devs;

/*get pointer by dev->priv*/
printf("%p\n",dev->priv);

/*get pointer using function:netdev_priv*/
printf("%p\n",netdev_priv(dev));
return 0;
}

Please refer to the comment int my program.
The results of the two are not equal, but it does not match as the
function(netdev_priv) describes.

Jul 3 '07 #6
In fact, I'm reading code about linux-driver.And it says we can get
the member *priv* through *netdev_priv* or dev->priv(not recommend).
Jul 3 '07 #7
!truth <no*********@asustek.com.cnwrites:
Thanks really,but i was still confused by question 1 and 3.

I modify my question 1:

1. the function(netdev_priv) is to get the member of *priv* in the
structure
net_device at line 414, which means that *dev->priv* equals
*netdev_priv(dev)*, but how it can do that?
[...]

Your use of '*' to delimit code snippets is confusing, especially when
you some of them are expressions involving pointers.

I sometimes use quotation marks for that purpose, as long as it's
clear that I'm not dealing with string literals.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 3 '07 #8
On Mon, 02 Jul 2007 19:21:30 -0700, !truth
<no*********@asustek.com.cnwrote:
>Thanks really,but i was still confused by question 1 and 3.

I modify my question 1:

1. the function(netdev_priv) is to get the member of *priv* in the
structure
net_device at line 414, which means that *dev->priv* equals
*netdev_priv(dev)*, but how it can do that?
In the code you provide, there is nothing in the function netdev_priv
that is at all related in any way to the member priv of the
structure.
>
I write down an similar program as follows:

#include <stdio.h>
struct device{
int a;
void *priv;
int c;
char d;
};
#define NETDEV_ALIGN 32
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)
static inline void *netdev_priv(struct device *dev)
{ return (char *)dev + ((sizeof(struct device)+
NETDEV_ALIGN_CONST)
& ~NETDEV_ALIGN_CONST);
}
int main()
{
struct device devs;
struct device *dev;
dev=&devs;

/*get pointer by dev->priv*/
printf("%p\n",dev->priv);
This invokes undefined behavior. all members of devs have
indeterminate values. Attempting to evaluate any of the members is
prohibited. Perhaps you meant &dev->priv as the second argument. But
then you would have to cast the expression to void*
>
/*get pointer using function:netdev_priv*/
printf("%p\n",netdev_priv(dev));
Calling netdev_priv for your struct invokes undefined behavior. The
function attempts to calculate an address which is not in the range
(start of struct, end of struct plus one byte). See my previous
response as to why dev must point to allocated memory unless
sizeof(devs) is an integral multiple of 32.
return 0;
}

Please refer to the comment int my program.
Sometimes comments are not correct. For that matter, the same is true
of the subject you use for this discussion. At no point in any of the
code you have shown is the address of a pointer calculated.
>The results of the two are not equal, but it does not match as the
function(netdev_priv) describes.
Go back and read my first comment above again. If you want to know
what netdev_priv really does, you can look at my previous response to
your post or you can ask in a newsgroup where this function is
topical.
Remove del for email
Jul 3 '07 #9
On 3 Jul, 03:21, !truth <noddy_zh...@asustek.com.cnwrote:
Thanks really,but i was still confused by question 1 and 3.
My post in reply - which you can see at
http://groups.google.co.uk/group/com...7cc060df1d26e0 if
nowhere else - answered your queries in some detail and pointed you at
more appropriate sources of information...

Did you miss it or didn't it help?

Jul 3 '07 #10
Keith Thompson <ks***@mib.orgwrites:
!truth <no*********@asustek.com.cnwrites:
1. the function(netdev_priv) is to get the member of *priv* in the
Your use of '*' to delimit code snippets is confusing, especially when
you some of them are expressions involving pointers.

I sometimes use quotation marks for that purpose, as long as it's
clear that I'm not dealing with string literals.
The convention I have settled on (and I have yet to see someone ask
for clarification; my day job includes compiler technical support) is
to quote code fragments with single-quotes when they appear within a
paragraph of non-code, and to set any multi-line fragments in their
own indented blocks. I try to also always refer to any function with
a pair of parentheses after its name.

Thus, I would refer to the function 'netdev_priv()' getting a member
of 'priv'. A larger sample of code might look like

if (somecondition) {
do_task();
}
weeble_counter++;

mlp
Jul 3 '07 #11
Mark L Pappin <ml*@acm.orgwrites:
Keith Thompson <ks***@mib.orgwrites:
>!truth <no*********@asustek.com.cnwrites:
1. the function(netdev_priv) is to get the member of *priv* in the
>Your use of '*' to delimit code snippets is confusing, especially when
you some of them are expressions involving pointers.

I sometimes use quotation marks for that purpose, as long as it's
clear that I'm not dealing with string literals.

The convention I have settled on (and I have yet to see someone ask
for clarification; my day job includes compiler technical support) is
to quote code fragments with single-quotes when they appear within a
paragraph of non-code, and to set any multi-line fragments in their
own indented blocks. I try to also always refer to any function with
a pair of parentheses after its name.

Thus, I would refer to the function 'netdev_priv()' getting a member
of 'priv'. A larger sample of code might look like

if (somecondition) {
do_task();
}
weeble_counter++;
That's a good idea; single quotes have less potential for ambiguity
than double quotes.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 3 '07 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

10 posts views Thread by Chris Mantoulidis | last post: by
3 posts views Thread by Bruno van Dooren | last post: by
204 posts views Thread by Alexei A. Frounze | last post: by
4 posts views Thread by Mark | last post: by
23 posts views Thread by bluejack | last post: by
69 posts views Thread by fieldfallow | last post: by
73 posts views Thread by Markus | last post: by
17 posts views Thread by Christian Wittrock | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.