]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
remote generator: Legacy support for hyper to long mappings
authorMatthias Bolte <matthias.bolte@googlemail.com>
Mon, 30 May 2011 10:58:57 +0000 (12:58 +0200)
committerMatthias Bolte <matthias.bolte@googlemail.com>
Wed, 1 Jun 2011 13:51:01 +0000 (15:51 +0200)
Remove some special case code that took care of mapping hyper to the
correct C types.

As the list of procedures that is allowed to map hyper to long is fixed
put it in the generator instead annotations in the .x files. This
results in simpler .x file parsing code.

Use macros for hyper to long assignments that perform overflow checks
when long is smaller than hyper. Map hyper to long long by default.

Suggested by Eric Blake.

configure.ac
daemon/remote.c
daemon/remote_generator.pl
src/remote/remote_driver.c

index b2ba930d48a9b2e59326713955d8ef0b0800d5a4..62cd17742a2eb95189f1d651903b5a7d9110f2b3 100644 (file)
@@ -117,6 +117,7 @@ if test "x$have_cpuid" = xyes; then
 fi
 AC_MSG_RESULT([$have_cpuid])
 
+AC_CHECK_SIZEOF([long])
 
 dnl Availability of various common functions (non-fatal if missing),
 dnl and various less common threadsafe functions
index 1897be8b50eaac9009e3ef3f1fcac0a4ec028c5b..64478cc7a2674749c3be02367a4a6417b3e03e24 100644 (file)
     virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,           \
                          __FUNCTION__, __LINE__, __VA_ARGS__)
 
+#if SIZEOF_LONG < 8
+# define HYPER_TO_TYPE(_type, _to, _from)                                     \
+    do {                                                                      \
+        if ((_from) != (_type)(_from)) {                                      \
+            virNetError(VIR_ERR_INTERNAL_ERROR,                               \
+                        _("conversion from hyper to %s overflowed"), #_type); \
+            goto cleanup;                                                     \
+        }                                                                     \
+        (_to) = (_from);                                                      \
+    } while (0)
+
+# define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from)
+# define HYPER_TO_ULONG(_to, _from) HYPER_TO_TYPE(unsigned long, _to, _from)
+#else
+# define HYPER_TO_LONG(_to, _from) (_to) = (_from)
+# define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
+#endif
+
 static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain);
 static virNetworkPtr get_nonnull_network(virConnectPtr conn, remote_nonnull_network network);
 static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface);
index ac808fb0c69023fac91b9a8db2d9a32615cf68c8..f85cc6b04b12e01e4242f1954a34a3ca7ef60585 100755 (executable)
@@ -174,6 +174,58 @@ while (<PROTOCOL>) {
 
 close(PROTOCOL);
 
+# this hash contains the procedures that are allowed to map [unsigned] hyper
+# to [unsigned] long for legacy reasons in their signature and return type.
+# this list is fixed. new procedures and public APIs have to map [unsigned]
+# hyper to [unsigned] long long
+my $long_legacy = {
+    DomainGetMaxMemory          => { ret => { memory => 1 } },
+    DomainGetInfo               => { ret => { maxMem => 1, memory => 1 } },
+    DomainMigrate               => { arg => { flags => 1, resource => 1 } },
+    DomainMigrate2              => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateBegin3         => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateConfirm3       => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateDirect         => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateFinish         => { arg => { flags => 1 } },
+    DomainMigrateFinish2        => { arg => { flags => 1 } },
+    DomainMigrateFinish3        => { arg => { flags => 1 } },
+    DomainMigratePeer2Peer      => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePerform        => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePerform3       => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepare        => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepare2       => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepare3       => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepareTunnel  => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepareTunnel3 => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateToURI          => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateToURI2         => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateVersion1       => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateVersion2       => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateVersion3       => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateSetMaxSpeed    => { arg => { bandwidth => 1 } },
+    DomainSetMaxMemory          => { arg => { memory => 1 } },
+    DomainSetMemory             => { arg => { memory => 1 } },
+    DomainSetMemoryFlags        => { arg => { memory => 1 } },
+    GetLibVersion               => { ret => { lib_ver => 1 } },
+    GetVersion                  => { ret => { hv_ver => 1 } },
+    NodeGetInfo                 => { ret => { memory => 1 } },
+};
+
+sub hyper_to_long
+{
+    my $proc_name = shift;
+    my $ret_or_arg = shift;
+    my $member = shift;
+
+    if ($long_legacy->{$proc_name} and
+        $long_legacy->{$proc_name}->{$ret_or_arg} and
+        $long_legacy->{$proc_name}->{$ret_or_arg}->{$member}) {
+        return 1;
+    } else {
+        return 0
+    }
+}
+
 #----------------------------------------------------------------------
 # Output
 
@@ -378,12 +430,29 @@ elsif ($opt_b) {
                     }
 
                     push(@args_list, "args->$1");
-                } elsif ($args_member =~ m/^(unsigned )?(int|hyper) (\S+);/) {
+                } elsif ($args_member =~ m/^(unsigned )?int (\S+);/) {
                     if (! @args_list) {
                         push(@args_list, "conn");
                     }
 
-                    push(@args_list, "args->$3");
+                    push(@args_list, "args->$2");
+                } elsif ($args_member =~ m/^(unsigned )?hyper (\S+);/) {
+                    if (! @args_list) {
+                        push(@args_list, "conn");
+                    }
+
+                    my $arg_name = $2;
+
+                    if (hyper_to_long($call->{ProcName}, "arg", $arg_name)) {
+                        my $type_name = $1; $type_name .= "long";
+                        my $sign = ""; $sign = "U" if ($1);
+
+                        push(@vars_list, "$type_name $arg_name");
+                        push(@getters_list, "    HYPER_TO_${sign}LONG($arg_name, args->$arg_name);\n");
+                        push(@args_list, "$arg_name");
+                    } else {
+                        push(@args_list, "args->$arg_name");
+                    }
                 } elsif ($args_member =~ m/^(\/)?\*/) {
                     # ignore comments
                 } else {
@@ -411,6 +480,10 @@ elsif ($opt_b) {
             foreach my $ret_member (@{$call->{ret_members}}) {
                 if ($multi_ret) {
                     if ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+)\[\S+\];/) {
+                        if ($2 eq "hyper" and hyper_to_long($call->{ProcName}, "ret", $3)) {
+                            die "legacy [u]long hyper arrays aren't supported";
+                        }
+
                         push(@ret_list, "memcpy(ret->$3, tmp.$3, sizeof ret->$3);");
                     } elsif ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+);/) {
                         push(@ret_list, "ret->$3 = tmp.$3;");
@@ -502,6 +575,10 @@ elsif ($opt_b) {
                         }
                     }
                 } elsif ($ret_member =~ m/^(?:unsigned )?hyper (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
+                    if (hyper_to_long($call->{ProcName}, "ret", $1)) {
+                        die "legacy [u]long hyper arrays aren't supported";
+                    }
+
                     push(@vars_list, "int len");
                     push(@ret_list, "ret->$1.$1_len = len;");
                     push(@free_list_on_error, "VIR_FREE(ret->$1.$1_val);");
@@ -523,14 +600,22 @@ elsif ($opt_b) {
                     # error out on unannotated arrays
                     die "hyper array without insert@<offset> annotation: $ret_member";
                 } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+);/) {
-                    my $type_name;
+                    my $type_name = $1;
                     my $ret_name = $2;
+                    my $ret_assign;
 
-                    $type_name = $1 if ($1);
-                    $type_name .= "long";
+                    if (hyper_to_long($call->{ProcName}, "ret", $ret_name)) {
+                        my $sign = ""; $sign = "U" if ($1);
+
+                        $type_name .= "long";
+                        $ret_assign = "HYPER_TO_${sign}LONG(ret->$ret_name, $ret_name);";
+                    } else {
+                        $type_name .= "long long";
+                        $ret_assign = "ret->$ret_name = $ret_name;";
+                    }
 
                     push(@vars_list, "$type_name $ret_name");
-                    push(@ret_list, "ret->$ret_name = $ret_name;");
+                    push(@ret_list, $ret_assign);
                     $single_ret_var = $ret_name;
 
                     if ($call->{ProcName} eq "DomainGetMaxMemory" or
@@ -888,22 +973,20 @@ elsif ($opt_k) {
                     push(@setters_list, "args.$arg_name.${arg_name}_val = (char *)$arg_name;");
                     push(@setters_list, "args.$arg_name.${arg_name}_len = ${arg_name}len;");
                     push(@args_check_list, { name => "\"$arg_name\"", arg => "${arg_name}len", limit => $limit });
-                } elsif ($args_member =~ m/^(unsigned )?(int|hyper) (\S+);/) {
-                    my $type_name;
-                    my $arg_name = $3;
-
-                    $type_name = $1 if ($1);
-                    $type_name .= $2;
-                    $type_name =~ s/hyper/long/;
-
-                    # SPECIAL: some hyper parameters map to long longs
-                    if (($call->{ProcName} eq "DomainMigrateSetMaxDowntime" and
-                         $arg_name eq "downtime") or
-                        ($call->{ProcName} eq "StorageVolUpload" and
-                         ($arg_name eq "offset" or $arg_name eq "length")) or
-                        ($call->{ProcName} eq "StorageVolDownload" and
-                         ($arg_name eq "offset" or $arg_name eq "length"))) {
-                        $type_name .= " long";
+                } elsif ($args_member =~ m/^(unsigned )?int (\S+);/) {
+                    my $type_name = $1; $type_name .= "int";
+                    my $arg_name = $2;
+
+                    push(@args_list, "$type_name $arg_name");
+                    push(@setters_list, "args.$arg_name = $arg_name;");
+                } elsif ($args_member =~ m/^(unsigned )?hyper (\S+);/) {
+                    my $type_name = $1;
+                    my $arg_name = $2;
+
+                    if (hyper_to_long($call->{ProcName}, "arg", $arg_name)) {
+                        $type_name .= "long";
+                    } else {
+                        $type_name .= "long long";
                     }
 
                     push(@args_list, "$type_name $arg_name");
@@ -961,13 +1044,23 @@ elsif ($opt_k) {
             foreach my $ret_member (@{$call->{ret_members}}) {
                 if ($multi_ret) {
                     if ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+)\[\S+\];/) {
+                        if ($2 eq "hyper" and hyper_to_long($call->{ProcName}, "ret", $3)) {
+                            die "legacy [u]long hyper arrays aren't supported";
+                        }
+
                         push(@ret_list, "memcpy(result->$3, ret.$3, sizeof result->$3);");
                     } elsif ($ret_member =~ m/<\S+>;/ or $ret_member =~ m/\[\S+\];/) {
                         # just make all other array types fail
                         die "unhandled type for multi-return-value for " .
                             "procedure $call->{name}: $ret_member";
                     } elsif ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+);/) {
-                        push(@ret_list, "result->$3 = ret.$3;");
+                        if ($2 eq "hyper" and hyper_to_long($call->{ProcName}, "ret", $3)) {
+                            my $sign = ""; $sign = "U" if ($1);
+
+                            push(@ret_list, "HYPER_TO_${sign}LONG(result->$3, ret.$3);");
+                        } else {
+                            push(@ret_list, "result->$3 = ret.$3;");
+                        }
                     } else {
                         die "unhandled type for multi-return-value for " .
                             "procedure $call->{name}: $ret_member";
@@ -1039,22 +1132,22 @@ elsif ($opt_k) {
                     $single_ret_var = "int rv = -1";
                     $single_ret_type = "int";
                 } elsif ($ret_member =~ m/^unsigned hyper (\S+);/) {
-                    my $arg_name = $1;
+                    my $ret_name = $1;
 
                     if ($call->{ProcName} =~ m/Get(Lib)?Version/) {
-                        push(@args_list, "unsigned long *$arg_name");
-                        push(@ret_list, "if ($arg_name) *$arg_name = ret.$arg_name;");
+                        push(@args_list, "unsigned long *$ret_name");
+                        push(@ret_list, "if ($ret_name) HYPER_TO_ULONG(*$ret_name, ret.$ret_name);");
                         push(@ret_list, "rv = 0;");
                         $single_ret_var = "int rv = -1";
                         $single_ret_type = "int";
-                    } elsif ($call->{ProcName} eq "NodeGetFreeMemory") {
-                        push(@ret_list, "rv = ret.$arg_name;");
-                        $single_ret_var = "unsigned long long rv = 0";
-                        $single_ret_type = "unsigned long long";
-                    } else {
-                        push(@ret_list, "rv = ret.$arg_name;");
+                    } elsif (hyper_to_long($call->{ProcName}, "ret", $ret_name)) {
+                        push(@ret_list, "HYPER_TO_ULONG(rv, ret.$ret_name);");
                         $single_ret_var = "unsigned long rv = 0";
                         $single_ret_type = "unsigned long";
+                    } else {
+                        push(@ret_list, "rv = ret.$ret_name;");
+                        $single_ret_var = "unsigned long long rv = 0";
+                        $single_ret_type = "unsigned long long";
                     }
                 } elsif ($ret_member =~ m/^(\/)?\*/) {
                     # ignore comments
index 8e3cd89bf22eb5eea4954333fc4252ef3abe3891..ac0c6f7aeff1074414a9082a01db265b32553ff0 100644 (file)
 
 #define VIR_FROM_THIS VIR_FROM_REMOTE
 
+#if SIZEOF_LONG < 8
+# define HYPER_TO_TYPE(_type, _to, _from)                                     \
+    do {                                                                      \
+        if ((_from) != (_type)(_from)) {                                      \
+            remoteError(VIR_ERR_INTERNAL_ERROR,                               \
+                        _("conversion from hyper to %s overflowed"), #_type); \
+            goto done;                                                        \
+        }                                                                     \
+        (_to) = (_from);                                                      \
+    } while (0)
+
+# define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from)
+# define HYPER_TO_ULONG(_to, _from) HYPER_TO_TYPE(unsigned long, _to, _from)
+#else
+# define HYPER_TO_LONG(_to, _from) (_to) = (_from)
+# define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
+#endif
+
 static int inside_daemon = 0;
 
 struct remote_thread_call;