Skip to contentSkip to conversation

linux/macros.h(new) and linux/list.h(mod) ...

PATCH Davide Libenzi 10 participants 22 messages Jul 5, 2001 – Jul 6, 2001

lore
Share & tools
lore
#0 lore raw

This patch add a new linux/macros.h that is supposed to host utility macros that otherwise developers are forced to define in their files. This version contain only min(), max() and abs().
The other change is to linux/list.h by adding two members list_first() and list_last().

- Davide

include/linux/list.h +4 -0
diff -NBbru linux-2.4.6.vanilla/include/linux/list.h linux-2.4.6/include/linux/list.h
@@ -148,6 +148,10 @@
  */
 #define list_for_each(pos, head) \
 	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_first(head)	(((head)->next != (head)) ? (head)->next: (struct list_head *) 0)
+
+#define list_last(head)	(((head)->prev != (head)) ? (head)->prev: (struct list_head *) 0)
 
 #endif /* __KERNEL__ || _LVM_H_INCLUDE */
 
include/linux/macros.h +19 -0
diff -NBbru linux-2.4.6.vanilla/include/linux/macros.h linux-2.4.6/include/linux/macros.h
@@ -0,0 +1,19 @@
+#ifndef _LINUX_MACROS_H
+#define _LINUX_MACROS_H
+
+
+#ifndef min
+#define min(a, b)	(((a) < (b)) ? (a): (b))
+#endif
+
+#ifndef max
+#define max(a, b)	(((a) > (b)) ? (a): (b))
+#endif
+
+#ifndef abs
+#define abs(a)	(((a) > 0) ? (a): -(a))
+#endif
+
+
+
+#endif
#1 lore raw
Quoted 3 lines · [email protected] said:

This patch add a new linux/macros.h that is supposed to host utility macros that otherwise developers are forced to define in their files. This version contain only min(), max() and abs().

Consider min(x++,y++). Try:

#define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_y:_x; }) #define max(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_x:_y; })

--
dwmw2

#2 lore raw
Quoted 6 lines · On 05-Jul-2001 David Woodhouse wrote:
Quoted 3 lines · [email protected] said:

This patch add a new linux/macros.h that is supposed to host utility macros that otherwise developers are forced to define in their files. This version contain only min(), max() and abs().

Quoted 6 lines

Consider min(x++,y++). Try:

#define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_y:_x; #})
#define max(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_x:_y; #})

Yep, it's better.

- Davide

#3 lore raw

Doesn't it add more overhead? I think using inline functions are much better.
Yes you have to define it for different types (char, short, int, long,
signed/unsigned).

Quoted 4 lines

Yep, it's better.

- Davide

#4 lore raw
Quoted 2 lines · [email protected] said:

Doesn't it add more overhead? I think using inline functions are
much better.

Why should it add overhead? Even the most naïve compiler ought to generate the same code, surely? I must admit I haven't looked hard at the output - it didn't even occur to me that it might produce suboptimal code.

Quoted 2 lines

Yes you have to define it for different types (char, short, int,
long, signed/unsigned).

Unfortunately, this being C means that you can't call them all by the same name. If I have to use unsigned_long_max(x,y) I'd rather type it out myself :)

--
dwmw2

#5 lore raw

-> From David Woodhouse <[email protected]> :

Quoted 8 lines
Quoted 2 lines · [email protected] said:

Doesn't it add more overhead? I think using inline functions are
much better.

Why should it add overhead? Even the most naïve compiler ought to generate the same code, surely? I must admit I haven't looked hard at the output - it didn't even occur to me that it might produce suboptimal code.

right, gcc -O2 does produce the same code (but -O does not).

Quoted 7 lines
Quoted 3 lines

Yes you have to define it for different types (char, short, int,
long, signed/unsigned).

Unfortunately, this being C means that you can't call them all by the same name. If I have to use unsigned_long_max(x,y) I'd rather type it out myself :)

Oops, I must be sleeping at that time :-)

Quoted 4 lines

--
dwmw2

#6 lore raw
In reply to Hua Zhong
Quoted 5 lines · On 05-Jul-2001 Hua Zhong wrote:

Doesn't it add more overhead? I think using inline functions are much better.
Yes you have to define it for different types (char, short, int, long,
signed/unsigned).

Yes it does.
Personally I know that min, max, etc... are macros and I never use unary operators inside.
Maybe a "unsafe" __max() and a "safe" max() could coexist.

- Davide

#7 lore raw
In reply to Davide Libenzi
Quoted 6 lines · Davide Libenzi
Quoted 5 lines · On 05-Jul-2001 David Woodhouse wrote:
Quoted 3 lines · [email protected] said:

This patch add a new linux/macros.h that is supposed to host utility macros that otherwise developers are forced to define in their files. This version contain only min(), max() and abs().

Quoted 8 lines
Quoted 6 lines

Consider min(x++,y++). Try:

#define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_y:_x; #})
#define max(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_x:_y; #})

Yep, it's better.

This program prints garbage:

	#define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_y:_x; })
	
	int main (void) { 
		int _x = 3, _y = 4; 
		printf("%i\n", min(_x, _y)); 
		return 0; 
	}

--
Daniel

#8 lore raw
Quoted 7 lines · [email protected] said:

This program prints garbage:

	#define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_y:_x; })
	 	int main (void) { 
		int _x = 3, _y = 4; 
		printf("%i\n", min(_x, _y)); 
		return 0; 
	} 

Life's a bitch.
cf. get_user(__ret_gu, __val_gu); (on i386)

Time to invent a gcc extension which gives us unique names? :)

--
dwmw2

#9 lore raw
Quoted 11 lines · On 05-Jul-2001 David Woodhouse wrote:
Quoted 8 lines · [email protected] said:

This program prints garbage:

     #define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y);
     #(_x>_y)?_y:_x; })
             int main (void) { 
             int _x = 3, _y = 4; 
             printf("%i\n", min(_x, _y)); 
             return 0; 
     } 
Quoted 4 lines

Life's a bitch.
cf. get_user(__ret_gu, __val_gu); (on i386)

Time to invent a gcc extension which gives us unique names? :)

Something like ::(x) to move up one level the name resolution for example.

- Davide

#10 lore raw
In reply to David Woodhouse
Quoted 4 lines

Life's a bitch.
cf. get_user(__ret_gu, __val_gu); (on i386)

Time to invent a gcc extension which gives us unique names? :)

#define min(a,b) __magic_minfoo(a,b, __var##__LINE__, __var2##__LINE__)

#define __magic_minfoo(A,B,C,D) \
	{ typeof(A) C = (A)  .... }

Alan

#11 lore raw

#define min(a,b) __magic_minfoo(a,b, __var##__LINE__, __var2##__LINE__)

#define __magic_minfoo(A,B,C,D) \
	({ typeof(A) C = (A); typeof(B) D = (B); C>D?D:C; })

void main(void)

{
	int __var11=5, __var211=7;

	printf("min(%d,%d) = %d (should be 11: %d)\n", __var11, __var211, min(__var11, __var211), __LINE__);
}

--
dwmw2

#12 lore raw
In reply to Alan Cox
Quoted 9 lines · On 05-Jul-2001 Alan Cox wrote:
Quoted 4 lines

Life's a bitch.
cf. get_user(__ret_gu, __val_gu); (on i386)

Time to invent a gcc extension which gives us unique names? :)

#define min(a,b) __magic_minfoo(a,b, __var##__LINE__, __var2##__LINE__)

#define __magic_minfoo(A,B,C,D) \
      { typeof(A) C = (A)  .... }

Anyway I think that :

int _a = 5;

for (;;) {
        int _a = _a;
        ...
}

must :

1) assign the upper level value of _a

or :

2) generate an compiler error

- Davide

#13 lore raw
Quoted 35 lines · you
Quoted 20 lines · Davide Libenzi
Quoted 9 lines · On 05-Jul-2001 Alan Cox wrote:
Quoted 4 lines

Life's a bitch.
cf. get_user(__ret_gu, __val_gu); (on i386)

Time to invent a gcc extension which gives us unique names? :)

#define min(a,b) __magic_minfoo(a,b, __var##__LINE__, __var2##__LINE__)

#define __magic_minfoo(A,B,C,D) \
      { typeof(A) C = (A)  .... }

Anyway I think that :

int _a = 5;

for (;;) {
        int _a = _a;
        ...
}
Quoted 7 lines

must :

1) assign the upper level value of _a

or :

2) generate an compiler error

Well, I happen to agree with you, but in this case, c's scope rules are stupidly broken, they are not going to change, and we have to live with it ;-)

--
Daniel

#14 lore raw
In reply to Alan Cox

Em Fri, Jul 06, 2001 at 12:08:55AM +0100, David Woodhouse escreveu:

Quoted 6 lines

#define min(a,b) __magic_minfoo(a,b, __var##__LINE__, __var2##__LINE__)

#define __magic_minfoo(A,B,C,D) \
	({ typeof(A) C = (A); typeof(B) D = (B); C>D?D:C; })
Quoted 6 lines

void main(void)

{
	int __var11=5, __var211=7;

	printf("min(%d,%d) = %d (should be 11: %d)\n", __var11, __var211, min(__var11, __var211), __LINE__);
}

Have you looked at the preprocessor output?

[acme@brinquedo /tmp]$ gcc -E a.c -o - # or 'cpp < a.c'
# 1 "a.c"
void main(void)

{
        int __var11=5, __var211=7;

        printf("min(%d,%d) = %d (should be 11: %d)\n", __var11, __var211,

+ ({ typeof( __var11 ) __var__LINE__ = ( __var11 ); typeof(
__var211 ) __var2__LINE__ = ( __var211 ); __var__LINE__ >
__var2__LINE__ ? __var2__LINE__ : __var__LINE__ ; }) , 11); }

I didn't found a way to generate unique variable names using __LINE__

- Arnaldo

#15 lore raw
In reply to Alan Cox

Alan Cox wrote:-

Quoted 4 lines

#define min(a,b) __magic_minfoo(a,b, __var##__LINE__, __var2##__LINE__)

#define __magic_minfoo(A,B,C,D) \
	{ typeof(A) C = (A)  .... }

No, that's buggy. You need an extra level of indirection to expand __LINE__. Arguments to ## are inserted in-place without expansion.

Neil.

#16 lore raw
In reply to Alan Cox

Em Fri, Jul 06, 2001 at 06:38:04PM +0100, Neil Booth escreveu:

Quoted 9 lines

Alan Cox wrote:-

Quoted 4 lines

#define min(a,b) __magic_minfoo(a,b, __var##__LINE__, __var2##__LINE__)

#define __magic_minfoo(A,B,C,D) \
	{ typeof(A) C = (A)  .... }

No, that's buggy. You need an extra level of indirection to expand __LINE__. Arguments to ## are inserted in-place without expansion.

yes, so lets try with another indirection and see if I'm missing something that you could clarify :)

[acme@brinquedo __attribute__]$ cat b.c
#define _min(a,b,line) __magic_minfoo(a,b, __var##line, __var2##line) #define min(a,b) _min(a,b,__LINE__)

#define __magic_minfoo(A,B,C,D) \
       ({ typeof(A) C = (A); typeof(B) D = (B); C>D?D:C; })

void main(void)

{
      int __var11=5, __var211=7;

      printf("min(%d,%d) = %d (should be 11: %d)\n", __var11, __var211,
             min(__var11, __var211), __LINE__);
}
[acme@brinquedo __attribute__]$ cpp < b.c
# 1 ""
void main(void)
{
      int __var11=5, __var211=7;

      printf("min(%d,%d) = %d (should be 11: %d)\n", __var11, __var211,
             ({ typeof(   __var11   )   __var__LINE__   = (   __var11   );

typeof( __var211 ) __var2__LINE__ = ( __var211 );
__var__LINE__ > __var2__LINE__ ? __var2__LINE__ : __var__LINE__ ; }) , 12);
}
[acme@brinquedo __attribute__]$

- Arnaldo

#17 lore raw
In reply to David Woodhouse

Better, but throwing __FILE__ in there would be good too...

Come to think of it, tho, we have multiple files named the same thing in multiple places on the kernel tree... even __var##__LINE__##__FILE__ isn't _guaranteed_ to be unique.

Matt

Quoted 18 lines · Alan Cox
Quoted 4 lines

Life's a bitch.
cf. get_user(__ret_gu, __val_gu); (on i386)

Time to invent a gcc extension which gives us unique names? :)

#define min(a,b) __magic_minfoo(a,b, __var##__LINE__, __var2##__LINE__)

#define __magic_minfoo(A,B,C,D) \
	{ typeof(A) C = (A)  .... }

Alan

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Signature · 6 lines
Matthew Dharm                              Home: [email protected] 
Maintainer, Linux USB Mass Storage Driver

Ye gods! I have feet??!
					-- Dust Puppy
User Friendly, 12/4/1997
#18 lore raw
Quoted 1 line

Better, but throwing __FILE__ in there would be good too...

Totally inappropriate. These are not global variables and a filename is not legal variable namespace anyway

#19 lore raw
In reply to David Woodhouse
Quoted 13 lines · On 20010706 Davide Libenzi wrote:
Quoted 11 lines · On 05-Jul-2001 David Woodhouse wrote:
Quoted 8 lines · [email protected] said:

This program prints garbage:

     #define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y);
     #(_x>_y)?_y:_x; })
             int main (void) { 
             int _x = 3, _y = 4; 
             printf("%i\n", min(_x, _y)); 
             return 0; 
     } 
Quoted 7 lines
Quoted 4 lines

Life's a bitch.
cf. get_user(__ret_gu, __val_gu); (on i386)

Time to invent a gcc extension which gives us unique names? :)

Something like ::(x) to move up one level the name resolution for example.

Tell gcc people to support <? and >? in C besides C++.

Signature · 4 lines
J.A. Magallon                           #  Let the source be with you...        
mailto:[email protected]
Mandrake Linux release 8.1 (Cooker) for i586
Linux werewolf 2.4.6-ac1 #2 SMP Thu Jul 5 01:15:49 CEST 2001 i686
#20 lore raw
In reply to David Woodhouse
Quoted 8 lines · On 20010705 Davide Libenzi wrote:
Quoted 6 lines · On 05-Jul-2001 David Woodhouse wrote:
Quoted 3 lines · [email protected] said:

This patch add a new linux/macros.h that is supposed to host utility macros that otherwise developers are forced to define in their files. This version contain only min(), max() and abs().

Quoted 8 lines
Quoted 6 lines

Consider min(x++,y++). Try:

#define min(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_y:_x; #})
#define max(x,y) ({ typeof((x)) _x = (x); typeof((y)) _y = (y); (_x>_y)?_x:_y; #})

Yep, it's better.

And there could be others also usefull:

#define ztst(x,y) (x ?: y) // x' if that is nonzero; otherwise, of y'

If g++ extensions worked in plain C, you just could write:
#define min(x,y) (x <? y)
#define max(x,y) (x >? y)

Signature · 4 lines
J.A. Magallon                           #  Let the source be with you...        
mailto:[email protected]
Mandrake Linux release 8.1 (Cooker) for i586
Linux werewolf 2.4.6-ac1 #2 SMP Thu Jul 5 01:15:49 CEST 2001 i686
#21 lore raw
In reply to Davide Libenzi
Quoted 3 lines · Davide Libenzi

This patch add a new linux/macros.h that is supposed to host utility macros that otherwise developers are forced to define in their files. This version contain only min(), max() and abs().

It's a good old tradition to put macros in uppercase letters. This would have avoided one fatal error in your patch, the conflict with the gcc built-in

	int abs(int);

which has it's prototype in include/linux/kernel.h. There's places which depend on this and would break with your macro.

Also, unless you have more macros in mind, it may make sense to just place MIN, MAX in kernel.h and of course to remove similar macro definitions throughout the kernel and replace them by the commonly defined ones.

--Kai